95 lines
3.0 KiB
Python
95 lines
3.0 KiB
Python
# 第 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()
|