<h2>概述</h2>
<p>这个问题已经解决了。然而,这个答案添加了一些实际的例子来帮助对数据类的基本理解。</p>
<blockquote>
<p>What exactly are python data classes and when is it best to use them?</p>
</blockquote>
<ol>
<li><em>代码生成器:生成样板代码;您可以选择在常规类中实现特殊方法,或者让数据类自动实现它们。</li>
<li><em>数据容器:保存数据(如元组和dict)的结构,通常带有点式的属性访问,如<a href="https://stackoverflow.com/questions/3357581/using-python-class-as-a-data-container">classes, ^{<cd1>} and others</a>。</li>
</ol>
<blockquote>
<p>"mutable namedtuples with default[s]"</p>
</blockquote>
<p>后一句话的意思是:</p>
<ul>
<li><em>可变</em>:默认情况下,可以重新分配数据类属性。您可以选择使它们不可变(参见下面的示例)。</li>
<li><em>namedtuple</em>:您有点式的属性访问,如<code>namedtuple</code>或常规类。</li>
<li><em>默认值:可以为属性指定默认值</li>
</ul>
<p>与普通类相比,您主要节省了输入样板代码的时间。</p>
<hr/>
<h2>特点</h2>
<p>下面是数据类特性的概述(请参阅摘要表中的示例)。</p>
<h2>你得到的</h2>
<p>以下是默认情况下从数据类获得的功能。</p>
<p><em>属性+表示+比较</em></p>
<pre><code>import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
</code></pre>
<p>以下默认值将自动设置为<code>True</code>:</p>
<pre><code>@dataclasses.dataclass(init=True, repr=True, eq=True)
</code></pre>
<h2>你能打开什么</h2>
<p>如果将适当的关键字设置为<code>True</code>,则可以使用其他功能。</p>
<p><em>顺序</em></p>
<pre><code>@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
</code></pre>
<p>现在实现了排序方法(重载运算符:<code>< > <= >=</code>),类似于使用更强的等式测试的<a href="https://docs.python.org/3/library/functools.html#functools.total_ordering" rel="noreferrer">^{<cd6>}</a>。</p>
<p><em>可哈希,可变</em></p>
<pre><code>@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
</code></pre>
<p>尽管对象可能是可变的(可能是不需要的),但是实现了散列。</p>
<p><em>可哈希,不可变</em></p>
<pre><code>@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
</code></pre>
<p>现在实现了散列,不允许更改对象或分配给属性。</p>
<p>总的来说,如果<code>unsafe_hash=True</code>或<code>frozen=True</code>,则对象是散列的。</p>
<p>有关更多详细信息,请参见原始<a href="https://github.com/ericvsmith/dataclasses/blob/d4c87c663feb0617fd8c7e6fe0a58882c4ccd468/dataclasses.py#L115" rel="noreferrer">hashing logic table</a>。</p>
<h2>你得不到的</h2>
<p>要获得以下特性,必须手动实现特殊方法:</p>
<p><em>无包装</em></p>
<pre><code>@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
</code></pre>
<p><em>优化</em></p>
<pre><code>@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
</code></pre>
<p>对象大小现在减小:</p>
<pre><code>>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
</code></pre>
<p>在某些情况下,<code>__slots__</code>还可以提高创建实例和访问属性的速度。此外,插槽不允许默认分配;否则,将引发<code>ValueError</code>。</p>
<p>有关此<a href="https://realpython.com/python-data-classes/#optimizing-data-classes" rel="noreferrer">blog post</a>中插槽的详细信息。</p>
<hr/>
<h2>汇总表</h2>
<pre><code>+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| 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__ |
| | | | |
| Unpackable+ | - | r, g, b = Color() | __iter__ |
| Optimization+ | - | sys.getsizeof(SlottedColor) -> 888 | __slots__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
</code></pre>
<p><sub><sup>+</sup>这些方法不是自动生成的,需要在数据类中手动实现。</sub></p>
<p><sub><sup>*</sup><code>__ne__</code>是<a href="https://github.com/ericvsmith/dataclasses/blob/d4c87c663feb0617fd8c7e6fe0a58882c4ccd468/dataclasses.py#L882" rel="noreferrer">not implemented</a>。</sub></p>
<hr/>
<h2>附加功能</h2>
<p><em>初始化后</em></p>
<pre><code>@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)
# RGBA(r=127, g=0, b=255, a=127)
</code></pre>
<p><em>遗传</em></p>
<pre><code>@dataclasses.dataclass
class RGBA(Color):
a : int = 0
</code></pre>
<p><em>转换</em></p>
<p>将数据类转换为元组或dict,<a href="https://stackoverflow.com/questions/51564841/creating-nested-dataclass-objects-in-python">recursively</a>:</p>
<pre><code>>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
</code></pre>
<p>限制</p>
<ul>
<li>缺少处理<a href="https://stackoverflow.com/questions/50764873/is-it-possible-to-use-args-in-a-dataclass">starred arguments</a>的机制</li>
</ul>
<hr/>
<h2>参考文献</h2>
<ul>
<li>R、 Hettinger的数据类:结束所有代码生成器的代码生成器</li>
<li>T、 Hunner的{a9}on<em>简单类:没有所有Cruft</em>的Python类</li>
<li>Python关于散列细节的<a href="https://docs.python.org/3/library/dataclasses.html#module-level-decorators-classes-and-functions" rel="noreferrer">documentation</a></li>
<li>真正的Python的<a href="https://realpython.com/python-data-classes/" rel="noreferrer">guide</a>on<em>Python 3.7中数据类的最终指南</em></li>
<li>A、 Shaw的<a href="https://hackernoon.com/a-brief-tour-of-python-3-7-data-classes-22ee5e046517" rel="noreferrer">blog post</a>on<em>Python 3.7数据类简介</li>
<li>E、 史密斯关于数据类的<a href="https://github.com/ericvsmith/dataclasses" rel="noreferrer">github repository</a></li>
</ul>