概述
这个问题已经回答了。但是,这个答案添加了一些实际的例子,以帮助基本理解数据类。
Python数据类到底是什么,在什么情况下最好使用它们?
- 代码生成器:生成样板代码;您可以选择在常规类中实现特殊方法,也可以让数据类自动实现这些方法。
- 数据容器:存储数据的结构(例如元组和字典),通常具有带点的属性访问,例如classes,
namedtuple
和其他。
"具有默认值的可变命名元组"
这里是后一个短语的含义:
- 可变的:默认情况下,数据类属性可以被重新赋值。您可以选择使它们不可变(见下面的示例)。
- 命名元组:您可以像命名元组或普通类一样拥有带点的属性访问。
- 默认值:您可以将默认值分配给属性。
与常规类相比,您主要节省输入样板代码。
特性
这是数据类功能的概述(简而言之?请参见下一节中的摘要表格)。
您将获得什么
以下是您从数据类中默认获取的功能。
属性 + 表示 + 比较
import dataclasses
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
这些默认值是通过自动将以下关键字设置为True
来提供的:
@dataclasses.dataclass(init=True, repr=True, eq=True)
你可以启用哪些功能
如果将适当的关键字设置为True
,则可以使用其他功能。
顺序
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
现在已经实现了排序方法(重载运算符:< > <= >=
),类似于functools.total_ordering
,具有更强的相等性测试。
可散列的,可变的
@dataclasses.dataclass(unsafe_hash=True)
class Color:
...
尽管对象可能是可变的(可能是不希望的),但哈希已经实现。
可哈希,不可变
@dataclasses.dataclass(frozen=True)
class Color:
...
现在已经实现了哈希,禁止更改对象或分配属性。
总体而言,如果unsafe_hash=True
或frozen=True
,则对象是可哈希的。
另请参阅具有更多详细信息的原始hashing logic table。
您无法获得的内容
要获得以下功能,必须手动实现特殊方法:
解包
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
优化
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
对象大小现在已被缩小:
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
在某些情况下,
__slots__
还可以提高创建实例和访问属性的速度。此外,slots 不允许默认赋值;否则,会引发一个
ValueError
。
关于slots的更多信息,请参见
blog post。
总结表
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Feature | Keyword | Example | Implement in a Class |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Attributes | init | Color().r -> 0 | __init__ |
| Representation | repr | Color() -> Color(r=0, g=0, b=0) | __repr__ |
| Comparision* | eq | Color() == Color(0, 0, 0) -> True | __eq__ |
| | | | |
| Order | order | sorted([Color(0, 50, 0), Color()]) -> ... | __lt__, __le__, __gt__, __ge__ |
| Hashable | unsafe_hash/frozen | {Color(), {Color()}} -> {Color(r=0, g=0, b=0)} | __hash__ |
| Immutable | frozen + eq | Color().r = 10 -> TypeError | __setattr__, __delattr__ |
| | | | |
| Unpacking+ | - | r, g, b = Color() | __iter__ |
| Optimization+ | - | sys.getsizeof(SlottedColor) -> 888 | __slots__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
+这些方法不是自动生成的,需要在数据类中手动实现。
* __ne__
不需要,因此 未实现。
额外功能
初始化后
@dataclasses.dataclass
class RGBA:
r : int = 0
g : int = 0
b : int = 0
a : float = 1.0
def __post_init__(self):
self.a : int = int(self.a * 255)
RGBA(127, 0, 255, 0.5)
继承
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
转换
将数据类递归地转换为元组或字典:
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{'r': 128, 'g': 0, 'b': 255}
限制
参考文献
- R. Hettinger在Dataclasses: The code generator to end all code generators上的演讲
- T. Hunner在Easier Classes: Python Classes Without All the Cruft上的演讲
- Python关于哈希细节的文档
- Real Python在The Ultimate Guide to Data Classes in Python 3.7上的指南
- A. Shaw在A brief tour of Python 3.7 data classes上的博客文章
- E. Smith的dataclassesGitHub仓库
@dataclass
的问题不会导致网站崩溃。 - ericnamedtuples
可以有默认值。请看这里:https://dev59.com/aWgu5IYBdhLWcg3wZmQm - MJB