使用PEP 557,数据类被引入到python标准库中。
它们使用@dataclass装饰器,并且应该是“带有默认值的可变命名元组”,但我不确定我是否理解这实际上意味着什么以及它们与普通类的区别。
@dataclass
python数据类到底是什么,什么时候最好使用它们?
数据类只是用于存储状态的常规类,不仅仅包含许多逻辑。每次创建一个主要由属性组成的类时,就创建了一个数据类。
该dataclasses模块的作用是使创建数据类 更加容易 。它为您处理了很多样板。
dataclasses
当您的数据类必须是可哈希的时,这一点尤其重要。这需要一种__hash__方法以及一种__eq__方法。如果添加自定义__repr__方法以简化调试,则可能会变得很冗长:
__hash__
__eq__
__repr__
class InventoryItem: '''Class for keeping track of an item in inventory.''' name: str unit_price: float quantity_on_hand: int = 0 def __init__( self, name: str, unit_price: float, quantity_on_hand: int = 0 ) -> None: self.name = name self.unit_price = unit_price self.quantity_on_hand = quantity_on_hand def total_cost(self) -> float: return self.unit_price * self.quantity_on_hand def __repr__(self) -> str: return ( 'InventoryItem(' f'name={self.name!r}, unit_price={self.unit_price!r}, ' f'quantity_on_hand={self.quantity_on_hand!r})' def __hash__(self) -> int: return hash((self.name, self.unit_price, self.quantity_on_hand)) def __eq__(self, other) -> bool: if not isinstance(other, InventoryItem): return NotImplemented return ( (self.name, self.unit_price, self.quantity_on_hand) == (other.name, other.unit_price, other.quantity_on_hand))
有了dataclasses它,您可以将其减少为:
from dataclasses import dataclass @dataclass(unsafe_hash=True) class InventoryItem: '''Class for keeping track of an item in inventory.''' name: str unit_price: float quantity_on_hand: int = 0 def total_cost(self) -> float: return self.unit_price * self.quantity_on_hand
同一类的装饰也可以产生比较方法(__lt__,__gt__等)和手柄不变性。
__lt__
__gt__
namedtuple类也是数据类,但是默认情况下是不变的(以及作为序列)。dataclasses在这方面更灵活,并且可以轻松地进行结构化,使其可以充当namedtuple类的相同角色。
namedtuple
PEP受该attrs项目的启发,该项目可以做更多的事情(包括广告位,验证器,转换器,元数据等)。
attrs
如果你想看到一些例子,我最近使用dataclasses了几个我的代码的问世解决方案,请参阅解决方案7天,8天,11天和20天。
如果要dataclasses在<3.7以下的Python版本中使用模块,则可以安装向后移植的模块(需要3.6)或使用上述attrs项目。