小编典典

什么是数据类,它们与普通类有何不同?

python

使用PEP 557,数据类被引入到python标准库中。

它们使用@dataclass装饰器,并且应该是“带有默认值的可变命名元组”,但我不确定我是否理解这实际上意味着什么以及它们与普通类的区别。

python数据类到底是什么,什么时候最好使用它们?


阅读 203

收藏
2020-12-20

共1个答案

小编典典

数据类只是用于存储状态的常规类,不仅仅包含许多逻辑。每次创建一个主要由属性组成的类时,就创建了一个数据类。

dataclasses模块的作用是使创建数据类 更加容易 。它为您处理了很多样板。

当您的数据类必须是可哈希的时,这一点尤其重要。这需要一种__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__等)和手柄不变性。

namedtuple类也是数据类,但是默认情况下是不变的(以及作为序列)。dataclasses在这方面更灵活,并且可以轻松地进行结构化,使其可以充当namedtuple类的相同角色

PEP受该attrs项目的启发,该项目可以做更多的事情(包括广告位,验证器,转换器,元数据等)。

如果你想看到一些例子,我最近使用dataclasses了几个我的代码的问世解决方案,请参阅解决方案7天8天11天20天

如果要dataclasses在<3.7以下的Python版本中使用模块,则可以安装向后移植的模块(需要3.6)或使用上述attrs项目。

2020-12-20