Files
hustoj/web/python-docs/library/dataclasses.html
2025-03-09 17:10:56 +08:00

644 lines
88 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>dataclasses --- 数据类 &#8212; Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="../_static/translations.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="在 Python 3.8.20 文档 中搜索"
href="../_static/opensearch.xml"/>
<link rel="author" title="关于这些文档" href="../about.html" />
<link rel="index" title="索引" href="../genindex.html" />
<link rel="search" title="搜索" href="../search.html" />
<link rel="copyright" title="版权所有" href="../copyright.html" />
<link rel="next" title="contextlib --- 为 with语句上下文提供的工具" href="contextlib.html" />
<link rel="prev" title="warnings ——控制警告信息" href="warnings.html" />
<link rel="canonical" href="https://docs.python.org/3/library/dataclasses.html" />
<style>
@media only screen {
table.full-width-table {
width: 100%;
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="快速搜索"/>
<input type="submit" value="转向"/>
</form>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">dataclasses</span></code> --- 数据类</a><ul>
<li><a class="reference internal" href="#module-level-decorators-classes-and-functions">模块级装饰器、类和函数</a></li>
<li><a class="reference internal" href="#post-init-processing">初始化后处理</a></li>
<li><a class="reference internal" href="#class-variables">类变量</a></li>
<li><a class="reference internal" href="#init-only-variables">仅初始化变量</a></li>
<li><a class="reference internal" href="#frozen-instances">冻结的实例</a></li>
<li><a class="reference internal" href="#inheritance">继承</a></li>
<li><a class="reference internal" href="#default-factory-functions">默认工厂函数</a></li>
<li><a class="reference internal" href="#mutable-default-values">可变的默认值</a></li>
<li><a class="reference internal" href="#exceptions">异常</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="warnings.html"
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">warnings</span></code> ——控制警告信息</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="contextlib.html"
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextlib</span></code> --- 为 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code>语句上下文提供的工具</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/dataclasses.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
这个文档所针对的是一个已不再受支持的 Python 旧版本。
你应当升级版本,并阅读
<a href="/3/library/dataclasses.html"> Python 当前稳定版本的文档</a>.
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
accesskey="I">索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="contextlib.html" title="contextlib --- 为 with语句上下文提供的工具"
accesskey="N">下一页</a> |</li>
<li class="right" >
<a href="warnings.html" title="warnings ——控制警告信息"
accesskey="P">上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="python.html" accesskey="U">Python 运行时服务</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="module-dataclasses">
<span id="dataclasses-data-classes"></span><h1><a class="reference internal" href="#module-dataclasses" title="dataclasses: Generate special methods on user-defined classes."><code class="xref py py-mod docutils literal notranslate"><span class="pre">dataclasses</span></code></a> --- 数据类<a class="headerlink" href="#module-dataclasses" title="永久链接至标题"></a></h1>
<p><strong>源码:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/dataclasses.py">Lib/dataclasses.py</a></p>
<hr class="docutils" />
<p>这个模块提供了一个装饰器和一些函数,用于自动添加生成的 <a class="reference internal" href="../glossary.html#term-special-method"><span class="xref std std-term">special method</span></a>,例如 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__repr__()</span></code></a> 到用户定义的类。 它最初描述于 <span class="target" id="index-6"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0557"><strong>PEP 557</strong></a></p>
<p>在这些生成的方法中使用的成员变量使用 <span class="target" id="index-7"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0526"><strong>PEP 526</strong></a> 类型注释定义。例如这段代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
<span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">InventoryItem</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Class for keeping track of an item in inventory.&quot;&quot;&quot;</span>
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
<span class="n">unit_price</span><span class="p">:</span> <span class="nb">float</span>
<span class="n">quantity_on_hand</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">total_cost</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">float</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">unit_price</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">quantity_on_hand</span>
</pre></div>
</div>
<p>除其他事情外,将添加 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> ,其看起来像:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">unit_price</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span> <span class="n">quantity_on_hand</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">unit_price</span> <span class="o">=</span> <span class="n">unit_price</span>
<span class="bp">self</span><span class="o">.</span><span class="n">quantity_on_hand</span> <span class="o">=</span> <span class="n">quantity_on_hand</span>
</pre></div>
</div>
<p>请注意,此方法会自动添加到类中:而不是在如上所示的 <code class="docutils literal notranslate"><span class="pre">InventoryItem</span></code> 定义中被直接指定。</p>
<div class="versionadded">
<p><span class="versionmodified added">3.7 新版功能.</span></p>
</div>
<section id="module-level-decorators-classes-and-functions">
<h2>模块级装饰器、类和函数<a class="headerlink" href="#module-level-decorators-classes-and-functions" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="dataclasses.dataclass">
<code class="sig-prename descclassname">&#64;</code><code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">dataclass</code><span class="sig-paren">(</span><em class="sig-param">*</em>, <em class="sig-param">init=True</em>, <em class="sig-param">repr=True</em>, <em class="sig-param">eq=True</em>, <em class="sig-param">order=False</em>, <em class="sig-param">unsafe_hash=False</em>, <em class="sig-param">frozen=False</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.dataclass" title="永久链接至目标"></a></dt>
<dd><p>这个函数是 <a class="reference internal" href="../glossary.html#term-decorator"><span class="xref std std-term">decorator</span></a> ,用于将生成的 <a class="reference internal" href="../glossary.html#term-special-method"><span class="xref std std-term">special method</span></a> 添加到类中,如下所述。</p>
<p><a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器检查类以找到 <code class="docutils literal notranslate"><span class="pre">field</span></code><code class="docutils literal notranslate"><span class="pre">field</span></code> 被定义为具有 <a class="reference internal" href="../glossary.html#term-variable-annotation"><span class="xref std std-term">类型标注</span></a> 的类变量。除了下面描述的两个例外,在 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 中没有任何内容检查变量标注中指定的类型。</p>
<p>这些字段在所有生成的方法中的顺序,都是它们在类定义中出现的顺序。</p>
<p><a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器将向类中添加各种“dunder”方法如下所述。如果类中已存在任何添加的方法则行为取决于参数如下所述。装饰器返回被调用的同一个类没有创建新类。</p>
<p>如果 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 仅用作没有参数的简单装饰器,它将使用它的函数签名中的默认值。也就是说,这三种 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 用法是等价的:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="o">...</span>
<span class="nd">@dataclass</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="o">...</span>
<span class="nd">@dataclass</span><span class="p">(</span><span class="n">init</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="nb">repr</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">eq</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">order</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">unsafe_hash</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">frozen</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p><a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 的参数有:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">init</span></code>: 如果为真值(默认),将生成一个 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法。</p>
<p>如果类已定义 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> ,则忽略此参数。</p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">repr</span></code> :如果为真值(默认),将生成一个 <a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__repr__()</span></code></a> 方法。 生成的 repr 字符串将具有类名以及每个字段的名称和 repr ,按照它们在类中定义的顺序。不包括标记为从 repr 中排除的字段。 例如:<code class="docutils literal notranslate"><span class="pre">InventoryItem(name='widget',</span> <span class="pre">unit_price=3.0,</span> <span class="pre">quantity_on_hand=10)</span></code></p>
<p>如果类已定义 <a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__repr__()</span></code></a> ,则忽略此参数。</p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">eq</span></code> 如果为true默认值将生成 <a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__eq__()</span></code></a> 方法。此方法将类作为其字段的元组按顺序比较。比较中的两个实例必须是相同的类型。</p>
<p>如果类已定义 <a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__eq__()</span></code></a> ,则忽略此参数。</p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">order</span></code> :如果为真值(默认为 <code class="docutils literal notranslate"><span class="pre">False</span></code> ),则 <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__le__" title="object.__le__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__le__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__ge__" title="object.__ge__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__ge__()</span></code></a> 方法将生成。 这将类作为其字段的元组按顺序比较。比较中的两个实例必须是相同的类型。如果 <code class="docutils literal notranslate"><span class="pre">order</span></code> 为真值并且 <code class="docutils literal notranslate"><span class="pre">eq</span></code> 为假值 ,则引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a></p>
<p>如果类已经定义了 <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__le__" title="object.__le__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__le__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a> 或者 <a class="reference internal" href="../reference/datamodel.html#object.__ge__" title="object.__ge__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__ge__()</span></code></a> 中的任意一个,将引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a></p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">unsafe_hash</span></code> :如果为 <code class="docutils literal notranslate"><span class="pre">False</span></code> (默认值),则根据 <code class="docutils literal notranslate"><span class="pre">eq</span></code><code class="docutils literal notranslate"><span class="pre">frozen</span></code> 的设置方式生成 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法。</p>
<p><a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 由内置的 <a class="reference internal" href="functions.html#hash" title="hash"><code class="xref py py-meth docutils literal notranslate"><span class="pre">hash()</span></code></a> 使用,当对象被添加到散列集合(如字典和集合)时。有一个 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 意味着类的实例是不可变的。可变性是一个复杂的属性,取决于程序员的意图, <a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__eq__()</span></code></a> 的存在性和行为,以及 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器中 <code class="docutils literal notranslate"><span class="pre">eq</span></code><code class="docutils literal notranslate"><span class="pre">frozen</span></code> 标志的值。</p>
<p>默认情况下, <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 不会隐式添加 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法,除非这样做是安全的。 它也不会添加或更改现有的明确定义的 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法。 设置类属性 <code class="docutils literal notranslate"><span class="pre">__hash__</span> <span class="pre">=</span> <span class="pre">None</span></code> 对 Python 具有特定含义,如 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 文档中所述。</p>
<p>如果 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 没有显式定义,或者它被设为 <code class="docutils literal notranslate"><span class="pre">None</span></code>,则 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> <em>可能</em> 会添加一个隐式 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法。 虽然并不推荐,但你可以用 <code class="docutils literal notranslate"><span class="pre">unsafe_hash=True</span></code> 来强制 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 创建一个 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法。 如果你的类在逻辑上不可变但却仍然可被修改那么可能就是这种情况。 这是一个特殊用例并且应当被仔细地考虑。</p>
<p>以下是隐式创建 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法的规则。请注意,你不能在数据类中都使用显式的 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法并设置 <code class="docutils literal notranslate"><span class="pre">unsafe_hash=True</span></code> ;这将导致 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a></p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">eq</span></code><code class="docutils literal notranslate"><span class="pre">frozen</span></code> 都是 true默认情况下 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 将为你生成一个 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法。如果 <code class="docutils literal notranslate"><span class="pre">eq</span></code> 为 true 且 <code class="docutils literal notranslate"><span class="pre">frozen</span></code> 为 false ,则 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 将被设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> ,标记它不可用(因为它是可变的)。如果 <code class="docutils literal notranslate"><span class="pre">eq</span></code> 为 false ,则 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 将保持不变,这意味着将使用超类的 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法(如果超类是 <a class="reference internal" href="functions.html#object" title="object"><code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></a> 这意味着它将回到基于id的hash</p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">frozen</span></code>: 如为真值 (默认值为 <code class="docutils literal notranslate"><span class="pre">False</span></code>),则对字段赋值将会产生异常。 这模拟了只读的冻结实例。 如果在类中定义了 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__delattr__" title="object.__delattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__delattr__()</span></code></a> 则将会引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a>。 参见下文的讨论。</p></li>
</ul>
<p>可以用普通的 Python 语法为各个 <code class="docutils literal notranslate"><span class="pre">field</span></code> 指定默认值:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="c1"># &#39;a&#39; has no default value</span>
<span class="n">b</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># assign a default value for &#39;b&#39;</span>
</pre></div>
</div>
<p>在这个例子中, <code class="docutils literal notranslate"><span class="pre">a</span></code><code class="docutils literal notranslate"><span class="pre">b</span></code> 都将包含在添加的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法中,它们将被定义为:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
</pre></div>
</div>
<p>如果没有默认值的字段跟在具有默认值的字段后,将引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> 。当这发生在单个类中时,或者作为类继承的结果时,都是如此。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.field">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">field</code><span class="sig-paren">(</span><em class="sig-param">*</em>, <em class="sig-param">default=MISSING</em>, <em class="sig-param">default_factory=MISSING</em>, <em class="sig-param">repr=True</em>, <em class="sig-param">hash=None</em>, <em class="sig-param">init=True</em>, <em class="sig-param">compare=True</em>, <em class="sig-param">metadata=None</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.field" title="永久链接至目标"></a></dt>
<dd><p>大多数时候,对于简单常见的用途,前述的功能已经足够了。而有些功能需要字段提供额外的信息来启用。为了满足这种对附加信息的需求,你可以通过调用提供的 <a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-func docutils literal notranslate"><span class="pre">field()</span></code></a> 函数来替换字段默认值。例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">mylist</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="nb">list</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">c</span><span class="o">.</span><span class="n">mylist</span> <span class="o">+=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</pre></div>
</div>
<p>如上所示, <code class="docutils literal notranslate"><span class="pre">MISSING</span></code> 值是一个 sentinel 对象,用于检测是否提供了 <code class="docutils literal notranslate"><span class="pre">default</span></code><code class="docutils literal notranslate"><span class="pre">default_factory</span></code> 参数。 使用此 sentinel 是因为 <code class="docutils literal notranslate"><span class="pre">None</span></code><code class="docutils literal notranslate"><span class="pre">default</span></code> 的有效值。没有代码应该直接使用 <code class="docutils literal notranslate"><span class="pre">MISSING</span></code> 值。</p>
<p><a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-func docutils literal notranslate"><span class="pre">field()</span></code></a> 的形参有:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">default</span></code>:如果提供,这将是该字段的默认值。设计这个形参是因为 <a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-meth docutils literal notranslate"><span class="pre">field()</span></code></a> 调用将会占据原来用来提供默认值的位置。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">default_factory</span></code>:如果提供,它必须是一个需要零个参数的可调用对象,当该字段需要一个默认值时,它将被调用。这能解决当默认值是可变对象时会带来的问题,如下所述。同时指定 <code class="docutils literal notranslate"><span class="pre">default</span></code><code class="docutils literal notranslate"><span class="pre">default_factory</span></code> 将产生错误。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">init</span></code> 如果为true默认值则该字段作为参数包含在生成的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法中。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">repr</span></code> 如果为true默认值则该字段包含在生成的 <a class="reference internal" href="../reference/datamodel.html#object.__repr__" title="object.__repr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__repr__()</span></code></a> 方法返回的字符串中。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">compare</span></code> 如果为true默认值则该字段包含在生成的相等性和比较方法中 <a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__eq__()</span></code></a> <a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a> 等等)。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">hash</span></code> :这可以是布尔值或 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。如果为true则此字段包含在生成的 <a class="reference internal" href="../reference/datamodel.html#object.__hash__" title="object.__hash__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 方法中。如果为 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值),请使用 <code class="docutils literal notranslate"><span class="pre">compare</span></code> 的值,这通常是预期的行为。如果字段用于比较,则应在 hash 中考虑该字段。不鼓励将此值设置为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 以外的任何值。</p>
<p>设置 <code class="docutils literal notranslate"><span class="pre">hash=False</span></code><code class="docutils literal notranslate"><span class="pre">compare=True</span></code> 的一个合理情况是,一个计算哈希值的代价很高的字段是检验等价性需要的,且还有其他字段可以用于计算类型的哈希值。可以从哈希值中排除该字段,但仍令它用于比较。</p>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">metadata</span></code>:可以是映射或 None。None 被视为一个空的字典。这个值将被包装在 <a class="reference internal" href="types.html#types.MappingProxyType" title="types.MappingProxyType"><code class="xref py py-func docutils literal notranslate"><span class="pre">MappingProxyType()</span></code></a> 中,使其只读,并暴露在 <a class="reference internal" href="#dataclasses.Field" title="dataclasses.Field"><code class="xref py py-class docutils literal notranslate"><span class="pre">Field</span></code></a> 对象上。数据类不使用它——它是作为第三方扩展机制提供的。多个第三方可以各自拥有自己的键,以用作元数据中的命名空间。</p></li>
</ul>
<p>如果通过调用 <a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-func docutils literal notranslate"><span class="pre">field()</span></code></a> 指定字段的默认值,则该字段对应的类属性的值将最终被替换为指定的 <code class="docutils literal notranslate"><span class="pre">default</span></code> 值。如果没有提供 <code class="docutils literal notranslate"><span class="pre">default</span></code>,那么将删除该字段对应的类属性。目的是在 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器运行之后,类属性将包含字段的默认值,和直接指定了默认值一样。例如,在运行如下代码之后:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">y</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="nb">repr</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="n">z</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="nb">repr</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="n">t</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">20</span>
</pre></div>
</div>
<p>类属性 <code class="docutils literal notranslate"><span class="pre">C.z</span></code> 将是 <code class="docutils literal notranslate"><span class="pre">10</span></code>,类属性 <code class="docutils literal notranslate"><span class="pre">C.t</span></code> 将是 <code class="docutils literal notranslate"><span class="pre">20</span></code>,类属性 <code class="docutils literal notranslate"><span class="pre">C.x</span></code><code class="docutils literal notranslate"><span class="pre">C.y</span></code> 将不设置。</p>
</dd></dl>
<dl class="class">
<dt id="dataclasses.Field">
<em class="property">class </em><code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">Field</code><a class="headerlink" href="#dataclasses.Field" title="永久链接至目标"></a></dt>
<dd><p><a class="reference internal" href="#dataclasses.Field" title="dataclasses.Field"><code class="xref py py-class docutils literal notranslate"><span class="pre">Field</span></code></a> 对象描述每个已定义的字段。这些对象在内部被创建,并由 <a class="reference internal" href="#dataclasses.fields" title="dataclasses.fields"><code class="xref py py-func docutils literal notranslate"><span class="pre">fields()</span></code></a> 模块级方法返回(见下)。用户永远不应该直接实例化 <a class="reference internal" href="#dataclasses.Field" title="dataclasses.Field"><code class="xref py py-class docutils literal notranslate"><span class="pre">Field</span></code></a> 对象。它的下列属性的含义是由文档规定的:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">name</span></code>:字段的名称。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">type</span></code>:字段的类型。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">default</span></code><code class="docutils literal notranslate"><span class="pre">default_factory</span></code><code class="docutils literal notranslate"><span class="pre">init</span></code><code class="docutils literal notranslate"><span class="pre">repr</span></code><code class="docutils literal notranslate"><span class="pre">hash</span></code><code class="docutils literal notranslate"><span class="pre">compare</span></code> 以及 <code class="docutils literal notranslate"><span class="pre">metadata</span></code> 与具有和 <a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-func docutils literal notranslate"><span class="pre">field()</span></code></a> 声明中相同的意义和值。</p></li>
</ul>
</div></blockquote>
<p>可能存在其他属性,但它们是私有的。用户不应检查或依赖于这些属性。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.fields">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">fields</code><span class="sig-paren">(</span><em class="sig-param">class_or_instance</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.fields" title="永久链接至目标"></a></dt>
<dd><p>返回一个能描述此数据类所包含的字段的元组,元组的每一项都是 <a class="reference internal" href="#dataclasses.Field" title="dataclasses.Field"><code class="xref py py-class docutils literal notranslate"><span class="pre">Field</span></code></a> 对象。接受数据类或数据类的实例。如果没有传递一个数据类或实例将引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a>。不返回 <code class="docutils literal notranslate"><span class="pre">ClassVar</span></code><code class="docutils literal notranslate"><span class="pre">InitVar</span></code> 等伪字段。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.asdict">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">asdict</code><span class="sig-paren">(</span><em class="sig-param">instance</em>, <em class="sig-param">*</em>, <em class="sig-param">dict_factory=dict</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.asdict" title="永久链接至目标"></a></dt>
<dd><p>将数据类 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 转换为字典(使用工厂函数 <code class="docutils literal notranslate"><span class="pre">dict_factory</span></code> )。每个数据类都转换为其字段的字典,如 <code class="docutils literal notranslate"><span class="pre">name:</span> <span class="pre">value</span></code> 对。数据类、字典、列表和元组被递归。例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">Point</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">y</span><span class="p">:</span> <span class="nb">int</span>
<span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">mylist</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Point</span><span class="p">]</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">asdict</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="p">{</span><span class="s1">&#39;x&#39;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">:</span> <span class="mi">20</span><span class="p">}</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">([</span><span class="n">Point</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">Point</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">4</span><span class="p">)])</span>
<span class="k">assert</span> <span class="n">asdict</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">==</span> <span class="p">{</span><span class="s1">&#39;mylist&#39;</span><span class="p">:</span> <span class="p">[{</span><span class="s1">&#39;x&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">},</span> <span class="p">{</span><span class="s1">&#39;x&#39;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">:</span> <span class="mi">4</span><span class="p">}]}</span>
</pre></div>
</div>
<p>引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> 如果 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 不是数据类实例。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.astuple">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">astuple</code><span class="sig-paren">(</span><em class="sig-param">instance</em>, <em class="sig-param">*</em>, <em class="sig-param">tuple_factory=tuple</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.astuple" title="永久链接至目标"></a></dt>
<dd><p>将数据类 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 转换为元组(通过使用工厂函数 <code class="docutils literal notranslate"><span class="pre">tuple_factory</span></code> )。每个数据类都转换为其字段值的元组。数据类、字典、列表和元组被递归。</p>
<p>继续前一个例子:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">assert</span> <span class="n">astuple</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">astuple</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">==</span> <span class="p">([(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">4</span><span class="p">)],)</span>
</pre></div>
</div>
<p>引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> 如果 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 不是数据类实例。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.make_dataclass">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">make_dataclass</code><span class="sig-paren">(</span><em class="sig-param">cls_name</em>, <em class="sig-param">fields</em>, <em class="sig-param">*</em>, <em class="sig-param">bases=()</em>, <em class="sig-param">namespace=None</em>, <em class="sig-param">init=True</em>, <em class="sig-param">repr=True</em>, <em class="sig-param">eq=True</em>, <em class="sig-param">order=False</em>, <em class="sig-param">unsafe_hash=False</em>, <em class="sig-param">frozen=False</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.make_dataclass" title="永久链接至目标"></a></dt>
<dd><p>创建一个名为 <code class="docutils literal notranslate"><span class="pre">cls_name</span></code> 的新数据类,字段为 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 中定义的字段,基类为 <code class="docutils literal notranslate"><span class="pre">bases</span></code> 中给出的基类,并使用 <code class="docutils literal notranslate"><span class="pre">namespace</span></code> 中给出的命名空间进行初始化。 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 是一个可迭代的元素,每个元素都是 <code class="docutils literal notranslate"><span class="pre">name</span></code><code class="docutils literal notranslate"><span class="pre">(name,</span> <span class="pre">type)</span></code><code class="docutils literal notranslate"><span class="pre">(name,</span> <span class="pre">type,</span> <span class="pre">Field)</span></code> 。 如果只提供``name`` <code class="docutils literal notranslate"><span class="pre">type</span></code><code class="docutils literal notranslate"><span class="pre">typing.Any</span></code><code class="docutils literal notranslate"><span class="pre">init</span></code><code class="docutils literal notranslate"><span class="pre">repr</span></code><code class="docutils literal notranslate"><span class="pre">eq</span></code><code class="docutils literal notranslate"><span class="pre">order</span></code><code class="docutils literal notranslate"><span class="pre">unsafe_hash</span></code><code class="docutils literal notranslate"><span class="pre">frozen</span></code> 的值与它们在 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 中的含义相同。</p>
<p>此函数不是必需的,因为任何用于创建带有 <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> 的新类的 Python 机制都可以进一步用 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 函数将创建的类转换为数据类。提供此函数是为了方便。例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">=</span> <span class="n">make_dataclass</span><span class="p">(</span><span class="s1">&#39;C&#39;</span><span class="p">,</span>
<span class="p">[(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="nb">int</span><span class="p">),</span>
<span class="s1">&#39;y&#39;</span><span class="p">,</span>
<span class="p">(</span><span class="s1">&#39;z&#39;</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="n">field</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="mi">5</span><span class="p">))],</span>
<span class="n">namespace</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;add_one&#39;</span><span class="p">:</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">})</span>
</pre></div>
</div>
<p>等价于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">y</span><span class="p">:</span> <span class="s1">&#39;typing.Any&#39;</span>
<span class="n">z</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">def</span> <span class="nf">add_one</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>
</pre></div>
</div>
</dd></dl>
<dl class="function">
<dt id="dataclasses.replace">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">replace</code><span class="sig-paren">(</span><em class="sig-param">instance</em>, <em class="sig-param">**changes</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.replace" title="永久链接至目标"></a></dt>
<dd><p>创建一个 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 相同类型的新对象,用 <code class="docutils literal notranslate"><span class="pre">changes</span></code> 中的值替换字段。如果 <code class="docutils literal notranslate"><span class="pre">instance</span></code> 不是数据类,则引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> 。如果 <code class="docutils literal notranslate"><span class="pre">changes</span></code> 中的值没有指定字段,则引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a></p>
<p>新返回的对象通过调用数据类的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法创建。这确保了如果存在 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> ,其也被调用。</p>
<p>如果存在没有默认值的仅初始化变量,必须在调用 <a class="reference internal" href="#dataclasses.replace" title="dataclasses.replace"><code class="xref py py-func docutils literal notranslate"><span class="pre">replace()</span></code></a> 时指定,以便它们可以传递给 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a><code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code></p>
<p><code class="docutils literal notranslate"><span class="pre">changes</span></code> 包含任何定义为 <code class="docutils literal notranslate"><span class="pre">init=False</span></code> 的字段是错误的。在这种情况下会引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a></p>
<p>提前提醒, 字段在 <a class="reference internal" href="#dataclasses.replace" title="dataclasses.replace"><code class="xref py py-func docutils literal notranslate"><span class="pre">replace()</span></code></a> 被调用时的行为是,当它们被初始化时,不是从源对象直接复制,而是在 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 中初始化。除非保持审慎,否则 <code class="docutils literal notranslate"><span class="pre">init=False</span></code> 字段大概很少能被正确地使用。如果有使用 <code class="docutils literal notranslate"><span class="pre">init=False</span></code> 的字段,那么使用另外的类构造器,或自定义 <code class="docutils literal notranslate"><span class="pre">replace()</span></code> 方法(或类似名称的方法)来复制实例,可能会更好。</p>
</dd></dl>
<dl class="function">
<dt id="dataclasses.is_dataclass">
<code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">is_dataclass</code><span class="sig-paren">(</span><em class="sig-param">class_or_instance</em><span class="sig-paren">)</span><a class="headerlink" href="#dataclasses.is_dataclass" title="永久链接至目标"></a></dt>
<dd><p>如果其形参为数据类,或其实例,返回 <code class="docutils literal notranslate"><span class="pre">True</span></code>,否则返回 <code class="docutils literal notranslate"><span class="pre">False</span></code></p>
<p>如果你需要知道一个类是否是一个数据类的实例(而不是一个数据类本身),那么再添加一个 <code class="docutils literal notranslate"><span class="pre">not</span> <span class="pre">isinstance(obj,</span> <span class="pre">type)</span></code> 检查:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_dataclass_instance</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
<span class="k">return</span> <span class="n">is_dataclass</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="nb">type</span><span class="p">)</span>
</pre></div>
</div>
</dd></dl>
</section>
<section id="post-init-processing">
<h2>初始化后处理<a class="headerlink" href="#post-init-processing" title="永久链接至标题"></a></h2>
<p>生成的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 代码将调用一个名为 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 的方法,如果在类上已经定义了 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 。它通常被称为 <code class="docutils literal notranslate"><span class="pre">self.__post_init__()</span></code> 。但是,如果定义了任何 <code class="docutils literal notranslate"><span class="pre">InitVar</span></code> 字段,它们也将按照它们在类中定义的顺序传递给 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 。 如果没有 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法生成,那么 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 将不会被自动调用。</p>
<p>在其他用途中,这允许初始化依赖于一个或多个其他字段的字段值。例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">a</span><span class="p">:</span> <span class="nb">float</span>
<span class="n">b</span><span class="p">:</span> <span class="nb">float</span>
<span class="n">c</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">init</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span>
</pre></div>
</div>
<p>有关将参数传递给 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 的方法,请参阅下面有关仅初始化变量的段落。另请参阅关于 <a class="reference internal" href="#dataclasses.replace" title="dataclasses.replace"><code class="xref py py-func docutils literal notranslate"><span class="pre">replace()</span></code></a> 处理 <code class="docutils literal notranslate"><span class="pre">init=False</span></code> 字段的警告。</p>
</section>
<section id="class-variables">
<h2>类变量<a class="headerlink" href="#class-variables" title="永久链接至标题"></a></h2>
<p>两个地方 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 实际检查字段类型的之一是确定字段是否是如 <span class="target" id="index-8"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0526"><strong>PEP 526</strong></a> 所定义的类变量。它通过检查字段的类型是否为 <code class="docutils literal notranslate"><span class="pre">typing.ClassVar</span></code> 来完成此操作。如果一个字段是一个 <code class="docutils literal notranslate"><span class="pre">ClassVar</span></code> ,它将被排除在考虑范围之外,并被数据类机制忽略。这样的 <code class="docutils literal notranslate"><span class="pre">ClassVar</span></code> 伪字段不会由模块级的 <a class="reference internal" href="#dataclasses.fields" title="dataclasses.fields"><code class="xref py py-func docutils literal notranslate"><span class="pre">fields()</span></code></a> 函数返回。</p>
</section>
<section id="init-only-variables">
<h2>仅初始化变量<a class="headerlink" href="#init-only-variables" title="永久链接至标题"></a></h2>
<p>另一个 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 检查类型注解地方是为了确定一个字段是否是一个仅初始化变量。它通过查看字段的类型是否为 <code class="docutils literal notranslate"><span class="pre">dataclasses.InitVar</span></code> 类型来实现。如果一个字段是一个 <code class="docutils literal notranslate"><span class="pre">InitVar</span></code> ,它被认为是一个称为仅初始化字段的伪字段。因为它不是一个真正的字段,所以它不会被模块级的 <a class="reference internal" href="#dataclasses.fields" title="dataclasses.fields"><code class="xref py py-func docutils literal notranslate"><span class="pre">fields()</span></code></a> 函数返回。仅初始化字段作为参数添加到生成的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法中,并传递给可选的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">__post_init__()</span></code> 方法。数据类不会使用它们。</p>
<p>例如,假设在创建类时没有为某个字段提供值,初始化时将从数据库中取值:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">i</span><span class="p">:</span> <span class="nb">int</span>
<span class="n">j</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">database</span><span class="p">:</span> <span class="n">InitVar</span><span class="p">[</span><span class="n">DatabaseType</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">database</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">j</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">database</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">j</span> <span class="o">=</span> <span class="n">database</span><span class="o">.</span><span class="n">lookup</span><span class="p">(</span><span class="s1">&#39;j&#39;</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">database</span><span class="o">=</span><span class="n">my_database</span><span class="p">)</span>
</pre></div>
</div>
<p>在这种情况下, <a class="reference internal" href="#dataclasses.fields" title="dataclasses.fields"><code class="xref py py-func docutils literal notranslate"><span class="pre">fields()</span></code></a> 将返回 <code class="docutils literal notranslate"><span class="pre">i</span></code><code class="docutils literal notranslate"><span class="pre">j</span></code><a class="reference internal" href="#dataclasses.Field" title="dataclasses.Field"><code class="xref py py-class docutils literal notranslate"><span class="pre">Field</span></code></a> 对象,但不包括 <code class="docutils literal notranslate"><span class="pre">database</span></code></p>
</section>
<section id="frozen-instances">
<h2>冻结的实例<a class="headerlink" href="#frozen-instances" title="永久链接至标题"></a></h2>
<p>无法创建真正不可变的 Python 对象。但是,通过将 <code class="docutils literal notranslate"><span class="pre">frozen=True</span></code> 传递给 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-meth docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器,你可以模拟不变性。在这种情况下,数据类将向类添加 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__delattr__" title="object.__delattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__delattr__()</span></code></a> 方法。 些方法在调用时会引发 <a class="reference internal" href="#dataclasses.FrozenInstanceError" title="dataclasses.FrozenInstanceError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">FrozenInstanceError</span></code></a></p>
<p>使用 <code class="docutils literal notranslate"><span class="pre">frozen=True</span></code> 时会有很小的性能损失: <code class="xref py py-meth docutils literal notranslate"><span class="pre">__</span> <span class="pre">init__()</span></code> 不能使用简单的赋值来初始化字段,并必须使用 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">object.__setattr__()</span></code></a></p>
</section>
<section id="inheritance">
<h2>继承<a class="headerlink" href="#inheritance" title="永久链接至标题"></a></h2>
<p>当数据类由 <a class="reference internal" href="#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-meth docutils literal notranslate"><span class="pre">dataclass()</span></code></a> 装饰器创建时,它会按反向 MRO 顺序(即,从 <a class="reference internal" href="functions.html#object" title="object"><code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></a> 开始)查看它的所有基类,并且将找到的每个数据类的字段添加到一个有序映射中。添加完所有基类字段后,它会将自己的字段添加到这个有序映射中。所有生成的方法都将使用这个有序映射。字段会遵守它们被插入的顺序,因此派生类会重写基类。一个例子:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">Base</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="n">Any</span> <span class="o">=</span> <span class="mf">15.0</span>
<span class="n">y</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
<span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="n">z</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">15</span>
</pre></div>
</div>
<p>最后的字段列表依次是 <code class="docutils literal notranslate"><span class="pre">x</span></code><code class="docutils literal notranslate"><span class="pre">y</span></code><code class="docutils literal notranslate"><span class="pre">z</span></code><code class="docutils literal notranslate"><span class="pre">x</span></code> 的最终类型是 <code class="docutils literal notranslate"><span class="pre">int</span></code> ,如类 <code class="docutils literal notranslate"><span class="pre">C</span></code> 中所指定的那样。</p>
<p><code class="docutils literal notranslate"><span class="pre">C</span></code> 生成的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 方法看起来像:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">z</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">10</span><span class="p">):</span>
</pre></div>
</div>
</section>
<section id="default-factory-functions">
<h2>默认工厂函数<a class="headerlink" href="#default-factory-functions" title="永久链接至标题"></a></h2>
<blockquote>
<div><p>如果一个 <a class="reference internal" href="#dataclasses.field" title="dataclasses.field"><code class="xref py py-func docutils literal notranslate"><span class="pre">field()</span></code></a> 指定了一个 <code class="docutils literal notranslate"><span class="pre">default_factory</span></code> ,当需要该字段的默认值时,将使用零参数调用它。例如,要创建列表的新实例,请使用:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">mylist</span><span class="p">:</span> <span class="nb">list</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="nb">list</span><span class="p">)</span>
</pre></div>
</div>
<p>如果一个字段被排除在 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 之外(使用 <code class="docutils literal notranslate"><span class="pre">init=False</span></code> )并且字段也指定 <code class="docutils literal notranslate"><span class="pre">default_factory</span></code> ,则默认的工厂函数将始终从生成的 <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> 函数调用。发生这种情况是因为没有其他方法可以为字段提供初始值。</p>
</div></blockquote>
</section>
<section id="mutable-default-values">
<h2>可变的默认值<a class="headerlink" href="#mutable-default-values" title="永久链接至标题"></a></h2>
<blockquote>
<div><p>Python 在类属性中存储默认成员变量值。思考这个例子,不使用数据类:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">element</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="n">o1</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">o2</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">o1</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">o2</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">o1</span><span class="o">.</span><span class="n">x</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">assert</span> <span class="n">o1</span><span class="o">.</span><span class="n">x</span> <span class="ow">is</span> <span class="n">o2</span><span class="o">.</span><span class="n">x</span>
</pre></div>
</div>
<p>请注意,类 <code class="docutils literal notranslate"><span class="pre">C</span></code> 的两个实例共享相同的类变量 <code class="docutils literal notranslate"><span class="pre">x</span></code> ,如预期的那样。</p>
<p>使用数据类,<em>如果</em> 此代码有效:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">D</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="n">List</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">element</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+=</span> <span class="n">element</span>
</pre></div>
</div>
<p>它生成的代码类似于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">D</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="o">=</span><span class="n">x</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">element</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+=</span> <span class="n">element</span>
<span class="k">assert</span> <span class="n">D</span><span class="p">()</span><span class="o">.</span><span class="n">x</span> <span class="ow">is</span> <span class="n">D</span><span class="p">()</span><span class="o">.</span><span class="n">x</span>
</pre></div>
</div>
<p>这与使用类 <code class="docutils literal notranslate"><span class="pre">C</span></code> 的原始示例具有相同的问题。也就是说,在创建类实例时没有为 <code class="docutils literal notranslate"><span class="pre">x</span></code> 指定值的类 <code class="docutils literal notranslate"><span class="pre">D</span></code> 的两个实例将共享相同的 <code class="docutils literal notranslate"><span class="pre">x</span></code> 副本。由于数据类只使用普通的 Python 类创建,因此它们也会共享此行为。数据类没有通用的方法来检测这种情况。相反,如果数据类检测到类型为 <code class="docutils literal notranslate"><span class="pre">list</span></code><code class="docutils literal notranslate"><span class="pre">dict</span></code><code class="docutils literal notranslate"><span class="pre">set</span></code> 的默认参数,则会引发 <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> 。这是一个部分解决方案,但它可以防止许多常见错误。</p>
<p>使用默认工厂函数是一种创建可变类型新实例的方法,并将其作为字段的默认值:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">D</span><span class="p">:</span>
<span class="n">x</span><span class="p">:</span> <span class="nb">list</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="nb">list</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">D</span><span class="p">()</span><span class="o">.</span><span class="n">x</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">D</span><span class="p">()</span><span class="o">.</span><span class="n">x</span>
</pre></div>
</div>
</div></blockquote>
</section>
<section id="exceptions">
<h2>异常<a class="headerlink" href="#exceptions" title="永久链接至标题"></a></h2>
<dl class="exception">
<dt id="dataclasses.FrozenInstanceError">
<em class="property">exception </em><code class="sig-prename descclassname">dataclasses.</code><code class="sig-name descname">FrozenInstanceError</code><a class="headerlink" href="#dataclasses.FrozenInstanceError" title="永久链接至目标"></a></dt>
<dd><p>在使用 <code class="docutils literal notranslate"><span class="pre">frozen=True</span></code> 定义的数据类上调用隐式定义的 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a><a class="reference internal" href="../reference/datamodel.html#object.__delattr__" title="object.__delattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__delattr__()</span></code></a> 时引发。 这是 <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">AttributeError</span></code></a> 的一个子类。</p>
</dd></dl>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">dataclasses</span></code> --- 数据类</a><ul>
<li><a class="reference internal" href="#module-level-decorators-classes-and-functions">模块级装饰器、类和函数</a></li>
<li><a class="reference internal" href="#post-init-processing">初始化后处理</a></li>
<li><a class="reference internal" href="#class-variables">类变量</a></li>
<li><a class="reference internal" href="#init-only-variables">仅初始化变量</a></li>
<li><a class="reference internal" href="#frozen-instances">冻结的实例</a></li>
<li><a class="reference internal" href="#inheritance">继承</a></li>
<li><a class="reference internal" href="#default-factory-functions">默认工厂函数</a></li>
<li><a class="reference internal" href="#mutable-default-values">可变的默认值</a></li>
<li><a class="reference internal" href="#exceptions">异常</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="warnings.html"
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">warnings</span></code> ——控制警告信息</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="contextlib.html"
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextlib</span></code> --- 为 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code>语句上下文提供的工具</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/dataclasses.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
>索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="contextlib.html" title="contextlib --- 为 with语句上下文提供的工具"
>下一页</a> |</li>
<li class="right" >
<a href="warnings.html" title="warnings ——控制警告信息"
>上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="python.html" >Python 运行时服务</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
最后更新于 12月 09, 2024.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
</div>
</body>
</html>