# 第 3-4 课完整示例:Python 特殊方法与数据类 # # 本示例对比普通类和 @dataclass,并演示 __str__、自动 __repr__、 # 自动 __eq__、__post_init__ 以及 field(default_factory=list)。 from dataclasses import dataclass, field class ManualProduct: """手动实现初始化、字符串显示和相等比较的普通类。""" def __init__(self, name: str, price: float) -> None: self.name = name self.price = price def __repr__(self) -> str: """返回适合开发和调试的对象表示。""" return f"ManualProduct(name={self.name!r}, price={self.price!r})" def __eq__(self, other: object) -> bool: """根据属性值判断两个商品是否相等。""" if not isinstance(other, ManualProduct): return NotImplemented return self.name == other.name and self.price == other.price @dataclass class Product: """数据类会根据字段自动生成常用特殊方法。""" name: str price: float def __post_init__(self) -> None: """在自动生成的 __init__ 执行后校验数据。""" if self.price < 0: raise ValueError("价格不能小于 0。") def __str__(self) -> str: """返回面向使用者的友好文字。""" return f"{self.name}:{self.price} 元" @dataclass class Cart: """购物车使用工厂函数为每个实例创建独立列表。""" owner: str items: list[Product] = field(default_factory=list) def add(self, product: Product) -> None: """向当前购物车添加商品。""" self.items.append(product) def main() -> None: """运行特殊方法与数据类示例。""" manual_one = ManualProduct("机械键盘", 500.0) manual_two = ManualProduct("机械键盘", 500.0) print("差异 1:普通类需要手动实现 Java 常见样板能力。") print(repr(manual_one)) print(f"两个普通类对象按内容相等:{manual_one == manual_two}") print() keyboard_one = Product("机械键盘", 500.0) keyboard_two = Product("机械键盘", 500.0) print("差异 2:@dataclass 自动生成 __init__、__repr__ 和 __eq__。") print(repr(keyboard_one)) print(f"两个数据类对象按字段相等:{keyboard_one == keyboard_two}") print() print("差异 3:__str__ 类似面向用户的 toString() 显示。") print(str(keyboard_one)) print() print("差异 4:类型注解不会自动校验,业务规则要在 __post_init__ 中实现。") try: Product("错误商品", -1.0) except ValueError as error: print(f"非法商品已被阻止:{error}") print() print("差异 5:default_factory 确保不同购物车使用不同列表。") first_cart = Cart("小明") second_cart = Cart("小红") first_cart.add(keyboard_one) print(f"小明的商品数:{len(first_cart.items)}") print(f"小红的商品数:{len(second_cart.items)}") if __name__ == "__main__": main()