You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中使用dataclasses与继承正确更新__repr__的方法

问题原因与解决方法

核心问题

你在__repr__里用super().isbn是错误的——父类BookMetadata的属性是实例属性,不是父类的类属性,直接通过self.isbn访问即可,不需要通过super()。super()主要用于调用父类的方法,而非直接访问实例属性。

修复后的__repr__方法

def __repr__(self) -> str:
    '''Update representation including parent and child class attributes.'''
    return f'RetailPrice(isbn={self.isbn}, title={self.title}, author={self.author}, publisher={self.publisher}, date_published={self.date_published}, price_usd={self.price_usd}, price_aud={self.price_aud}, price_eur={self.price_eur}, price_gbp={self.price_gbp})'

优化你的dataclass用法

你的子类RetailPrice加了@dataclass()装饰器但手动编写__init__,违背了dataclass的设计初衷,会导致自动生成的方法失效,还容易引发问题。正确做法是让dataclass自动生成构造方法:

优化后的完整代码

from dataclasses import dataclass
from typing import Any
from datetime import datetime


@dataclass
class BookMetadata:
    '''Parent class.'''
    isbn: str 
    title: str 
    author: str
    publisher: str
    date_published: int
    
    def format_time(self, unix: int) -> str:
        '''Convert unix time to %Y-%m-%d.'''
        return datetime.fromtimestamp(int(str(unix)[0:10])).strftime('%Y-%m-%d')
    
    def __post_init__(self):
        '''Change attributes after assignment.'''
        # 把UNIX时间转为YYYY-MM-DD格式
        self.date_published = self.format_time(self.date_published)
    

@dataclass
class RetailPrice(BookMetadata):
    '''Child class.'''
    price_usd: float
    price_aud: float
    price_eur: float
    price_gbp: float
    
    def stringify(self, obj: Any) -> str:
        '''Turn object into string.'''
        return str(obj)
    
    def __post_init__(self):
        '''Change attribute values after assignment.'''
        # 先执行父类的__post_init__处理日期
        super().__post_init__()
        self.price_usd = self.stringify(self.price_usd)
    
    def __repr__(self) -> str:
        '''Update representation including parent and child class attributes.'''
        return f'RetailPrice(isbn={self.isbn}, title={self.title}, author={self.author}, publisher={self.publisher}, date_published={self.date_published}, price_usd={self.price_usd}, price_aud={self.price_aud}, price_eur={self.price_eur}, price_gbp={self.price_gbp})'

优化点说明

  • 删掉子类手动编写的__init__,dataclass会自动生成包含父类+子类所有字段的构造方法,无需手动调用父类__init__。
  • 子类__post_init__先调用super().__post_init__(),确保父类的日期转换逻辑优先执行,再处理子类自身属性。
  • __repr__直接用self.xxx访问所有属性——实例继承了父类的全部实例属性,不管父类还是子类属性都能通过self直接获取。

为什么super().isbn会报错

super()返回的是代理对象,仅能访问父类的类属性或方法;而isbn是实例化后绑定到self上的实例属性,所以通过super()无法访问,必须直接用self。

内容的提问来源于stack exchange,提问作者FaCoffee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:55:30