如何从Python数据类的__dict__中移除指定实例或类属性?
解决方案
要让dataclass的__dict__排除指定属性,除了重写__dict__,还有几种更优雅的实现方式:
方法1:用property包装私有属性
将meta改为通过property访问,实际存储在私有属性中,这样私有属性可以命名为不希望出现在__dict__中的名字(比如_meta);如果连私有属性都不想出现在__dict__里,还可以结合__slots__实现:
from dataclasses import dataclass @dataclass class VCP: voltage: float | None = None current: float | None = None power: float | None = None _meta: dict | None = None # 私有存储属性 @property def meta(self): return self._meta @meta.setter def meta(self, value): self._meta = value # 使用示例 vcp = VCP(voltage=15.0, current=10.0, power=45) vcp.meta = {"time": 15} print(vcp.__dict__) # 输出: {'voltage': 15.0, 'current': 10.0, 'power': 45, '_meta': {'time': 15}}
结合__slots__彻底移除__dict__:
from dataclasses import dataclass @dataclass class VCP: __slots__ = ('voltage', 'current', 'power', '_meta') voltage: float | None = None current: float | None = None power: float | None = None _meta: dict | None = None @property def meta(self): return self._meta @meta.setter def meta(self, value): self._meta = value # 使用示例 vcp = VCP(voltage=15.0, current=10.0, power=45) vcp.meta = {"time": 15} print(vcp.__dict__) # 输出: AttributeError: 'VCP' object has no attribute '__dict__'
方法2:用弱引用字典存储属性
把meta的存储转移到类级别的弱引用字典中,这样实例的__dict__完全不会包含meta相关内容,同时弱引用不会阻碍实例的垃圾回收:
from dataclasses import dataclass import weakref @dataclass class VCP: voltage: float | None = None current: float | None = None power: float | None = None # 类级别的弱引用字典,存储每个实例的meta _meta_storage = weakref.WeakKeyDictionary() @property def meta(self): return self._meta_storage.get(self) @meta.setter def meta(self, value): self._meta_storage[self] = value # 使用示例 vcp = VCP(voltage=15.0, current=10.0, power=45) vcp.meta = {"time": 15} print(vcp.__dict__) # 输出: {'voltage': 15.0, 'current': 10.0, 'power': 45}
方法3:优化重写__dict__的方式
如果倾向于保留原属性名,重写__dict__的方式也可以更简洁:
from dataclasses import dataclass @dataclass class VCP: voltage: float | None = None current: float | None = None power: float | None = None meta: dict | None = None @property def __dict__(self): # 过滤掉meta字段 return {k: v for k, v in super().__getattribute__('__dict__').items() if k != 'meta'} # 使用示例 vcp = VCP(voltage=15.0, current=10.0, power=45, meta={"time": 15}) print(vcp.__dict__) # 输出: {'voltage': 15.0, 'current': 10.0, 'power': 45}
注意
Python的dataclasses模块本身没有提供直接标记属性排除在__dict__之外的参数,因为dataclass的设计就是将所有字段映射为实例属性并纳入__dict__(除非使用__slots__)。上面的方法都是通过属性封装或存储转移来实现需求。
内容的提问来源于stack exchange,提问作者Jérôme O.
相关产品推荐
相关产品推荐

