如何让Python @dataclass动态计算派生属性值?
问题解决:让dataclass动态计算属性值
问题根源
你当前在类定义阶段直接赋值satisfied和loud,这两个是类变量,只会在类加载时执行一次,使用的是字段的默认值(food_tasty=False、restaurant_noisiness_dB=None),不会随实例化时传入的参数更新。
解决方案1:使用__post_init__方法(推荐)
在dataclass初始化完成后,基于实例的实际属性值计算这两个字段:
from dataclasses import dataclass, astuple class BaseSatisfaction(): satisfied: list[bool] loud: bool | int @dataclass class ClientSatisfaction(BaseSatisfaction): food_tasty: bool = False served_quickly: bool = False restaurant_noisiness_dB: None | float = None def __post_init__(self): # 基于当前实例的属性动态计算 self.satisfied = [self.food_tasty, self.served_quickly] self.loud = 0 if self.restaurant_noisiness_dB is None else self.restaurant_noisiness_dB > 100 happy_client = ClientSatisfaction(food_tasty=True, served_quickly=True) rage_client = ClientSatisfaction(restaurant_noisiness_dB=120) print("======== Happy Client =========") print(happy_client.__dict__.items()) print(f"Happy client is satisfied: {happy_client.satisfied}") print(f"How loud was it?: {happy_client.loud}") print("======== Rage Client =========") print(rage_client.__dict__.items()) print(f"Rage client is satisfied: {rage_client.satisfied}") print(f"How loud was it?: {rage_client.loud}")
运行结果
======== Happy Client ========= dict_items([('food_tasty', True), ('served_quickly', True), ('restaurant_noisiness_dB', None), ('satisfied', [True, True]), ('loud', 0)]) Happy client is satisfied: [True, True] How loud was it?: 0 ======== Rage Client ========= dict_items([('food_tasty', False), ('served_quickly', False), ('restaurant_noisiness_dB', 120), ('satisfied', [False, False]), ('loud', True)]) Rage client is satisfied: [False, False] How loud was it?: True
解决方案2:使用@property装饰器(动态更新场景)
如果需要在实例属性修改后,satisfied和loud能自动更新,可将它们定义为属性:
from dataclasses import dataclass, astuple class BaseSatisfaction(): @property def satisfied(self) -> list[bool]: ... @property def loud(self) -> bool | int: ... @dataclass class ClientSatisfaction(BaseSatisfaction): food_tasty: bool = False served_quickly: bool = False restaurant_noisiness_dB: None | float = None @property def satisfied(self) -> list[bool]: return [self.food_tasty, self.served_quickly] @property def loud(self) -> bool | int: return 0 if self.restaurant_noisiness_dB is None else self.restaurant_noisiness_dB > 100
优势
当你修改实例属性时,比如happy_client.food_tasty = False,再次访问happy_client.satisfied会自动返回[False, True],无需手动重新计算。
内容的提问来源于stack exchange,提问作者Call_me_Utka
相关产品推荐
相关产品推荐

