uTools-Manuals/docs/python/functools.html
2019-04-21 11:50:48 +08:00

163 lines
56 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.

<div class="body" role="main"><div class="section" id="module-functools"><h1><span class="yiyi-st" id="yiyi-10">10.2. <a class="reference internal" href="#module-functools" title="functools: Higher-order functions and operations on callable objects."><code class="xref py py-mod docutils literal"><span class="pre">functools</span></code></a> - 可调用对象的高阶函数和操作</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/functools.py">Lib / functools.py</a></span></p><p><span class="yiyi-st" id="yiyi-12"><a class="reference internal" href="#module-functools" title="functools: Higher-order functions and operations on callable objects."><code class="xref py py-mod docutils literal"><span class="pre">functools</span></code></a>模块用于高阶函数:作用于或返回其他函数的函数。</span><span class="yiyi-st" id="yiyi-13">一般来说,对于这个模块,任何可调用对象都可以被视为函数。</span></p><p><span class="yiyi-st" id="yiyi-14"><a class="reference internal" href="#module-functools" title="functools: Higher-order functions and operations on callable objects."><code class="xref py py-mod docutils literal"><span class="pre">functools</span></code></a> 模块定义了以下函数︰</span></p><dl class="function"><dt id="functools.cmp_to_key"><span class="yiyi-st" id="yiyi-15"><code class="descclassname">functools.</code><code class="descname">cmp_to_key</code><span class="sig-paren">(</span><em>func</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-16">将旧风格的比较函数转换为<a class="reference internal" href="../glossary.html#term-key-function"><span class="xref std std-term">key函数</span></a></span><span class="yiyi-st" id="yiyi-17">用于接受key函数的工具例如<a class="reference internal" href="functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal"><span class="pre">sorted()</span></code></a><a class="reference internal" href="functions.html#min" title="min"><code class="xref py py-func docutils literal"><span class="pre">min()</span></code></a><a class="reference internal" href="functions.html#max" title="max"><code class="xref py py-func docutils literal"><span class="pre">max()</span></code></a><a class="reference internal" href="heapq.html#heapq.nlargest" title="heapq.nlargest"><code class="xref py py-func docutils literal"><span class="pre">heapq.nlargest </span></code></a><a class="reference internal" href="heapq.html#heapq.nsmallest" title="heapq.nsmallest"><code class="xref py py-func docutils literal"><span class="pre">heapq.nsmallest()</span></code></a><a class="reference internal" href="itertools.html#itertools.groupby" title="itertools.groupby"><code class="xref py py-func docutils literal"><span class="pre">itertools.groupby()</span></code></a>)。</span><span class="yiyi-st" id="yiyi-18">此函数主要用作从支持使用比较函数的Python 2转换的程序的过渡工具。</span></p><p><span class="yiyi-st" id="yiyi-19">比较函数是任何一个可调用的函数且包含两个参数对参数进行比较如果小于返回负数等于返回0大于返回正数。</span><span class="yiyi-st" id="yiyi-20">Key函数是一个可调用对象它接受一个参数并返回另一个值作为排序的键。</span></p><p><span class="yiyi-st" id="yiyi-21">示例:</span></p><pre><code class="language-python"><span></span><span class="nb">sorted</span><span class="p">(</span><span class="n">iterable</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">cmp_to_key</span><span class="p">(</span><span class="n">locale</span><span class="o">.</span><span class="n">strcoll</span><span class="p">))</span> <span class="c1"># locale-aware sort order</span>
</code></pre><p><span class="yiyi-st" id="yiyi-22">有关排序示例和简要排序教程,请参阅<a class="reference internal" href="../howto/sorting.html#sortinghowto"><span>排序HOWTO</span></a></span></p><div class="versionadded"><p><span class="yiyi-st" id="yiyi-23"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div></dd></dl><dl class="function"><dt id="functools.lru_cache"><span class="yiyi-st" id="yiyi-24"><code class="descclassname">@</code><code class="descclassname">functools.</code><code class="descname">lru_cache</code><span class="sig-paren">(</span><em>maxsize=128</em>, <em>typed=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-25">装饰器用一个memoizing可调用函数来包装一个函数它可以保存最近的<em>maxsize</em>个调用。</span><span class="yiyi-st" id="yiyi-26">当使用相同的参数定期调用昂贵的或I / O绑定的函数时可以节省时间。</span></p><p><span class="yiyi-st" id="yiyi-27">由于字典用于缓存结果,函数的位置和关键字参数必须是可哈希的。</span></p><p><span class="yiyi-st" id="yiyi-28">如果<em>maxsize</em>设置为None则禁用LRU功能并且缓存可以无限制增长。</span><span class="yiyi-st" id="yiyi-29"><em>maxsize</em>是二的幂时LRU功能执行得最好。</span></p><p><span class="yiyi-st" id="yiyi-30">如果<em>类型</em>设置为True则不同类型的函数参数将单独缓存。</span><span class="yiyi-st" id="yiyi-31">例如,<code class="docutils literal"><span class="pre">f(3)</span></code><code class="docutils literal"><span class="pre">f(3.0)</span></code>将被视为具有不同结果的不同调用。</span></p><p><span class="yiyi-st" id="yiyi-32">To help measure the effectiveness of the cache and tune the <em>maxsize</em> parameter, the wrapped function is instrumented with a <code class="xref py py-func docutils literal"><span class="pre">cache_info()</span></code> function that returns a <a class="reference internal" href="../glossary.html#term-named-tuple"><span class="xref std std-term">named tuple</span></a> showing <em>hits</em>, <em>misses</em>, <em>maxsize</em> and <em>currsize</em>. </span><span class="yiyi-st" id="yiyi-33">在多线程环境中,命中和未命中是近似的。</span></p><p><span class="yiyi-st" id="yiyi-34">装饰器还提供了用于清除或使缓存无效的<code class="xref py py-func docutils literal"><span class="pre">cache_clear()</span></code>函数。</span></p><p><span class="yiyi-st" id="yiyi-35">原始的底层函数可以通过<code class="xref py py-attr docutils literal"><span class="pre">__wrapped__</span></code>属性访问。</span><span class="yiyi-st" id="yiyi-36">这对于内省,绕过缓存或者用不同的缓存重新封装函数很有用。</span></p><p><span class="yiyi-st" id="yiyi-37">当最近的呼叫是即将来电的最佳预测因子时,<a class="reference external" href="https://en.wikipedia.org/wiki/Cache_algorithms#Examples">LRU最近最少使用高速缓存</a>效果最好(例如,新闻服务器上最受欢迎的文章往往每天都更改)。</span><span class="yiyi-st" id="yiyi-38">缓存的大小限制确保缓存不会在长时间运行的进程如Web服务器上不受限制地增长。</span></p><p><span class="yiyi-st" id="yiyi-39">用于静态Web内容的LRU缓存示例</span></p><pre><code class="language-python"><span></span><span class="nd">@lru_cache</span><span class="p">(</span><span class="n">maxsize</span><span class="o">=</span><span class="mi">32</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_pep</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="s1">'Retrieve text of a Python Enhancement Proposal'</span>
<span class="n">resource</span> <span class="o">=</span> <span class="s1">'http://www.python.org/dev/peps/pep-</span><span class="si">%04d</span><span class="s1">/'</span> <span class="o">%</span> <span class="n">num</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
<span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">except</span> <span class="n">urllib</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">HTTPError</span><span class="p">:</span>
<span class="k">return</span> <span class="s1">'Not Found'</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">290</span><span class="p">,</span> <span class="mi">308</span><span class="p">,</span> <span class="mi">320</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">218</span><span class="p">,</span> <span class="mi">320</span><span class="p">,</span> <span class="mi">279</span><span class="p">,</span> <span class="mi">289</span><span class="p">,</span> <span class="mi">320</span><span class="p">,</span> <span class="mi">9991</span><span class="p">:</span>
<span class="o">...</span> <span class="n">pep</span> <span class="o">=</span> <span class="n">get_pep</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="o">...</span> <span class="nb">print</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">pep</span><span class="p">))</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">get_pep</span><span class="o">.</span><span class="n">cache_info</span><span class="p">()</span>
<span class="n">CacheInfo</span><span class="p">(</span><span class="n">hits</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">misses</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span> <span class="n">maxsize</span><span class="o">=</span><span class="mi">32</span><span class="p">,</span> <span class="n">currsize</span><span class="o">=</span><span class="mi">8</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-40">使用高速缓存实现<a class="reference external" href="https://en.wikipedia.org/wiki/Dynamic_programming">动态规划</a>技术有效计算<a class="reference external" href="https://en.wikipedia.org/wiki/Fibonacci_number">斐波纳契数</a>的示例:</span></p><pre><code class="language-python"><span></span><span class="nd">@lru_cache</span><span class="p">(</span><span class="n">maxsize</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
<span class="k">return</span> <span class="n">n</span>
<span class="k">return</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="p">[</span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">)]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</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> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">,</span> <span class="mi">144</span><span class="p">,</span> <span class="mi">233</span><span class="p">,</span> <span class="mi">377</span><span class="p">,</span> <span class="mi">610</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">fib</span><span class="o">.</span><span class="n">cache_info</span><span class="p">()</span>
<span class="n">CacheInfo</span><span class="p">(</span><span class="n">hits</span><span class="o">=</span><span class="mi">28</span><span class="p">,</span> <span class="n">misses</span><span class="o">=</span><span class="mi">16</span><span class="p">,</span> <span class="n">maxsize</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">currsize</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span>
</code></pre><div class="versionadded"><p><span class="yiyi-st" id="yiyi-41"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-42"><span class="versionmodified">在版本3.3中更改:</span>添加了<em>类型</em>选项。</span></p></div></dd></dl><dl class="function"><dt id="functools.total_ordering"><span class="yiyi-st" id="yiyi-43"><code class="descclassname">@</code><code class="descclassname">functools.</code><code class="descname">total_ordering</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-44">给定一个定义了一个或多个富比较排序方法的类,该方法提供了一个类装饰器。</span><span class="yiyi-st" id="yiyi-45">这简化了指定所有可能的富比较操作的工作量。</span></p><p><span class="yiyi-st" id="yiyi-46">类必须定义<a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal"><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"><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"><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"><span class="pre">__ge__()</span></code></a></span><span class="yiyi-st" id="yiyi-47">此外,该类应提供一个<a class="reference internal" href="../reference/datamodel.html#object.__eq__" title="object.__eq__"><code class="xref py py-meth docutils literal"><span class="pre">__eq__()</span></code></a>方法。</span></p><p><span class="yiyi-st" id="yiyi-48">示例:</span></p><pre><code class="language-python"><span></span><span class="nd">@total_ordering</span>
<span class="k">class</span> <span class="nc">Student</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">_is_valid_operand</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">hasattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="s2">"lastname"</span><span class="p">)</span> <span class="ow">and</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="s2">"firstname"</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_valid_operand</span><span class="p">(</span><span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="k">return</span> <span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">lastname</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="bp">self</span><span class="o">.</span><span class="n">firstname</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span> <span class="o">==</span>
<span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">lastname</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">other</span><span class="o">.</span><span class="n">firstname</span><span class="o">.</span><span class="n">lower</span><span class="p">()))</span>
<span class="k">def</span> <span class="nf">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_valid_operand</span><span class="p">(</span><span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">NotImplemented</span>
<span class="k">return</span> <span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">lastname</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="bp">self</span><span class="o">.</span><span class="n">firstname</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span> <span class="o">&lt;</span>
<span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">lastname</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">other</span><span class="o">.</span><span class="n">firstname</span><span class="o">.</span><span class="n">lower</span><span class="p">()))</span>
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-49">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-50">虽然这个装饰器使得容易创建行为良好的完全有序类型,但<em></em>是以导致比较方法的较慢执行和更复杂的堆栈跟踪为代价的。</span><span class="yiyi-st" id="yiyi-51">如果性能基准测试表明这是给定应用程序的瓶颈,则实施所有六种丰富的比较方法可能提供一个容易的速度提升。</span></p></div><div class="versionadded"><p><span class="yiyi-st" id="yiyi-52"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-53"><span class="versionmodified">在版本3.4中更改:</span>现在支持从无法识别的类型的基础比较函数返回未实现。</span></p></div></dd></dl><dl class="function"><dt id="functools.partial"><span class="yiyi-st" id="yiyi-54"><code class="descclassname">functools.</code><code class="descname">partial</code><span class="sig-paren">(</span><em>func</em>, <em>*args</em>, <em>**keywords</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-55">返回一个新的<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象,该对象在调用时的行为将类似采用位置参数<em>args</em>和关键字参数<em>keywords</em><em>func</em>的调用。</span><span class="yiyi-st" id="yiyi-56">如果提供多个参数调用, 它们会被追加给 <em>args</em></span><span class="yiyi-st" id="yiyi-57">如果提供额外的关键字参数, 它们会扩展和覆盖 <em>keywords</em></span><span class="yiyi-st" id="yiyi-58">大致相当于:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">partial</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">keywords</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">newfunc</span><span class="p">(</span><span class="o">*</span><span class="n">fargs</span><span class="p">,</span> <span class="o">**</span><span class="n">fkeywords</span><span class="p">):</span>
<span class="n">newkeywords</span> <span class="o">=</span> <span class="n">keywords</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">newkeywords</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">fkeywords</span><span class="p">)</span>
<span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">*</span><span class="n">fargs</span><span class="p">,</span> <span class="o">**</span><span class="n">newkeywords</span><span class="p">)</span>
<span class="n">newfunc</span><span class="o">.</span><span class="n">func</span> <span class="o">=</span> <span class="n">func</span>
<span class="n">newfunc</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span>
<span class="n">newfunc</span><span class="o">.</span><span class="n">keywords</span> <span class="o">=</span> <span class="n">keywords</span>
<span class="k">return</span> <span class="n">newfunc</span>
</code></pre><p><span class="yiyi-st" id="yiyi-59"><a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal"><span class="pre">partial()</span></code></a>用于部分函数应用程序,其“冻结”函数的参数和/或关键字的某些部分,从而产生具有简化声明的新对象。</span><span class="yiyi-st" id="yiyi-60">例如,<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal"><span class="pre">partial()</span></code></a>可用于创建一个可调用对象,其行为类似于<a class="reference internal" href="functions.html#int" title="int"><code class="xref py py-func docutils literal"><span class="pre">int()</span></code></a>函数但<em>base</em>参数默认为2</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">partial</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">basetwo</span> <span class="o">=</span> <span class="n">partial</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">basetwo</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="s1">'Convert base 2 string to an int.'</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">basetwo</span><span class="p">(</span><span class="s1">'10010'</span><span class="p">)</span>
<span class="go">18</span>
</code></pre></dd></dl><dl class="class"><dt id="functools.partialmethod"><span class="yiyi-st" id="yiyi-61"><em class="property">class </em><code class="descclassname">functools.</code><code class="descname">partialmethod</code><span class="sig-paren">(</span><em>func</em>, <em>*args</em>, <em>**keywords</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-62">返回一个新的<a class="reference internal" href="#functools.partialmethod" title="functools.partialmethod"><code class="xref py py-class docutils literal"><span class="pre">partialmethod</span></code></a>描述器,它的行为类似于<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>,除了它被设计为用作方法定义而不是直接可调用。</span></p><p><span class="yiyi-st" id="yiyi-63"><em>func</em>必须是<a class="reference internal" href="../glossary.html#term-descriptor"><span class="xref std std-term">descriptor</span></a>或可调用对象(这两个对象都像常规函数一样被处理为描述器)。</span></p><p><span class="yiyi-st" id="yiyi-64">When <em>func</em> is a descriptor (such as a normal Python function, <a class="reference internal" href="functions.html#classmethod" title="classmethod"><code class="xref py py-func docutils literal"><span class="pre">classmethod()</span></code></a>, <a class="reference internal" href="functions.html#staticmethod" title="staticmethod"><code class="xref py py-func docutils literal"><span class="pre">staticmethod()</span></code></a>, <code class="xref py py-func docutils literal"><span class="pre">abstractmethod()</span></code> or another instance of <a class="reference internal" href="#functools.partialmethod" title="functools.partialmethod"><code class="xref py py-class docutils literal"><span class="pre">partialmethod</span></code></a>), calls to <code class="docutils literal"><span class="pre">__get__</span></code> are delegated to the underlying descriptor, and an appropriate <a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a> object returned as the result.</span></p><p><span class="yiyi-st" id="yiyi-65"><em>func</em>是非描述符可调用时,将动态创建适当的绑定方法。</span><span class="yiyi-st" id="yiyi-66">在作为方法使用时它的行为类似于普通的Python函数<em>self</em>参数将被插入作为第一个位置参数,甚至在<em>args</em><em>t2&gt;提供给<a class="reference internal" href="#functools.partialmethod" title="functools.partialmethod"><code class="xref py py-class docutils literal"><span class="pre">partialmethod</span></code></a>构造函数。</em></span></p><p><span class="yiyi-st" id="yiyi-67">示例:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Cell</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">_alive</span> <span class="o">=</span> <span class="kc">False</span>
<span class="gp">... </span> <span class="nd">@property</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">alive</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_alive</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">set_state</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">_alive</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">set_alive</span> <span class="o">=</span> <span class="n">partialmethod</span><span class="p">(</span><span class="n">set_state</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">set_dead</span> <span class="o">=</span> <span class="n">partialmethod</span><span class="p">(</span><span class="n">set_state</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="n">Cell</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">alive</span>
<span class="go">False</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">set_alive</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">alive</span>
<span class="go">True</span>
</code></pre><div class="versionadded"><p><span class="yiyi-st" id="yiyi-68"><span class="versionmodified">版本3.4中的新功能。</span></span></p></div></dd></dl><dl class="function"><dt id="functools.reduce"><span class="yiyi-st" id="yiyi-69"><code class="descclassname">functools.</code><code class="descname">reduce</code><span class="sig-paren">(</span><em>function</em>, <em>iterable</em><span class="optional">[</span>, <em>initializer</em><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-70">将带有两个参数的 <em>function</em> 从左到右累积应用到 <em>sequence</em> 的元素中,以将该序列规约为单个值。</span><span class="yiyi-st" id="yiyi-71">例如,<code class="docutils literal"><span class="pre">reduce(lambda</span> <span class="pre">x,</span> <span class="pre">y:</span> <span class="pre">x+y,</span> <span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3,</span> <span class="pre">4,</span> <span class="pre">5])</span></code> 计算 <code class="docutils literal"><span class="pre">((((1+2)+3)+4)+5)</span></code></span><span class="yiyi-st" id="yiyi-72">左参数 <em>x</em> 是累积值,右参数 <em>y</em> 是来自 <em>sequence</em> 的更新值。</span><span class="yiyi-st" id="yiyi-73">如果存在可选的 <em>initializer</em>,则它将放置在计算序列的元素之前,并在序列为空时用作默认值。</span><span class="yiyi-st" id="yiyi-74">如果未提供 <em>initializer</em><em>sequence</em> 只包含一个元素,则返回第一个元素。</span></p><p><span class="yiyi-st" id="yiyi-75">大致相当于:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">reduce</span><span class="p">(</span><span class="n">function</span><span class="p">,</span> <span class="n">iterable</span><span class="p">,</span> <span class="n">initializer</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">it</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">iterable</span><span class="p">)</span>
<span class="k">if</span> <span class="n">initializer</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">initializer</span>
<span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">it</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">function</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">element</span><span class="p">)</span>
<span class="k">return</span> <span class="n">value</span>
</code></pre></dd></dl><dl class="function"><dt id="functools.singledispatch"><span class="yiyi-st" id="yiyi-76"> <code class="descclassname">@</code><code class="descclassname">functools.</code><code class="descname">singledispatch</code><span class="sig-paren">(</span><em>default</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-77">将函数转换为<a class="reference internal" href="../glossary.html#term-single-dispatch"><span class="xref std std-term">single-dispatch</span></a> <a class="reference internal" href="../glossary.html#term-generic-function"><span class="xref std std-term">generic function</span></a></span></p><p><span class="yiyi-st" id="yiyi-78">要定义通用函数,请使用<code class="docutils literal"><span class="pre">@singledispatch</span></code>装饰器进行装饰。</span><span class="yiyi-st" id="yiyi-79">注意,分派发生在第一个参数的类型上,相应地创建你的函数:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">singledispatch</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nd">@singledispatch</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">fun</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Let me just say,"</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-80">要向函数添加重载的实现,请使用通用函数的<code class="xref py py-func docutils literal"><span class="pre">register()</span></code>属性。</span><span class="yiyi-st" id="yiyi-81">它是一个装饰器,接受一个类型参数和装饰实现该类型的操作的函数:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nd">@fun</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">_</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Strength in numbers, eh?"</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nd">@fun</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">_</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Enumerate this:"</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">elem</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">arg</span><span class="p">):</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">elem</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-82">要启用注册lambda和预先存在的函数可以以函数形式使用<code class="xref py py-func docutils literal"><span class="pre">register()</span></code>属性:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">nothing</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Nothing."</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="kc">None</span><span class="p">),</span> <span class="n">nothing</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-83"><code class="xref py py-func docutils literal"><span class="pre">register()</span></code>属性返回未装饰函数原函数该函数使装饰器堆叠pickle化序列化以及为每个变体独立创建单元测试</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nd">@fun</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="nb">float</span><span class="p">)</span>
<span class="gp">... </span><span class="nd">@fun</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">Decimal</span><span class="p">)</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">fun_num</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"Half of your number:"</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">arg</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun_num</span> <span class="ow">is</span> <span class="n">fun</span>
<span class="go">False</span>
</code></pre><p><span class="yiyi-st" id="yiyi-84">当被调用时,泛型函数调度第一个参数的类型:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">(</span><span class="s2">"Hello, world."</span><span class="p">)</span>
<span class="go">Hello, world.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">(</span><span class="s2">"test."</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">Let me just say, test.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">(</span><span class="mi">42</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">Strength in numbers, eh? 42</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">([</span><span class="s1">'spam'</span><span class="p">,</span> <span class="s1">'spam'</span><span class="p">,</span> <span class="s1">'eggs'</span><span class="p">,</span> <span class="s1">'spam'</span><span class="p">],</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">Enumerate this:</span>
<span class="go">0 spam</span>
<span class="go">1 spam</span>
<span class="go">2 eggs</span>
<span class="go">3 spam</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="go">Nothing.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="p">(</span><span class="mf">1.23</span><span class="p">)</span>
<span class="go">0.615</span>
</code></pre><p><span class="yiyi-st" id="yiyi-85">在没有针对特定类型的注册实现的情况下,其方法解析顺序用于找到更通用的实现。</span><span class="yiyi-st" id="yiyi-86"><code class="docutils literal"><span class="pre">@singledispatch</span></code>装饰的原始函数是为基础<code class="docutils literal"><span class="pre">object</span></code>类型注册的,这意味着如果没有找到更好的实现,则使用它。</span></p><p><span class="yiyi-st" id="yiyi-87">要检查通用函数为给定类型选择的实现,请使用<code class="docutils literal"><span class="pre">dispatch()</span></code>属性:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="nb">float</span><span class="p">)</span>
<span class="go">&lt;function fun_num at 0x1035a2840&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="nb">dict</span><span class="p">)</span> <span class="c1"># note: default implementation</span>
<span class="go">&lt;function fun at 0x103fe0000&gt;</span>
</code></pre><p><span class="yiyi-st" id="yiyi-88">要访问所有注册的实现,请使用只读<code class="docutils literal"><span class="pre">registry</span></code>属性:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">registry</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
<span class="go">dict_keys([&lt;class 'NoneType'&gt;, &lt;class 'int'&gt;, &lt;class 'object'&gt;,</span>
<span class="go"> &lt;class 'decimal.Decimal'&gt;, &lt;class 'list'&gt;,</span>
<span class="go"> &lt;class 'float'&gt;])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">registry</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span>
<span class="go">&lt;function fun_num at 0x1035a2840&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fun</span><span class="o">.</span><span class="n">registry</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span>
<span class="go">&lt;function fun at 0x103fe0000&gt;</span>
</code></pre><div class="versionadded"><p><span class="yiyi-st" id="yiyi-89"><span class="versionmodified">版本3.4中的新功能。</span></span></p></div></dd></dl><dl class="function"><dt id="functools.update_wrapper"><span class="yiyi-st" id="yiyi-90"><code class="descclassname">functools.</code><code class="descname">update_wrapper</code><span class="sig-paren">(</span><em>wrapper</em>, <em>wrapped</em>, <em>assigned=WRAPPER_ASSIGNMENTS</em>, <em>updated=WRAPPER_UPDATES</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-91">更新一个 <em>wrapper</em> 函数让其更像一个 <em>wrapped</em> 函数。</span><span class="yiyi-st" id="yiyi-92">可选的参数是一个元祖,来指定原函数哪些属性被直接分配给装饰器中的匹配属性 ,哪些装饰器属性使用来自原函数的相应属性来更新。</span><span class="yiyi-st" id="yiyi-93">The default values for these arguments are the module level constants <code class="docutils literal"><span class="pre">WRAPPER_ASSIGNMENTS</span></code> (which assigns to the wrapper functions <code class="docutils literal"><span class="pre">__module__</span></code>, <code class="docutils literal"><span class="pre">__name__</span></code>, <code class="docutils literal"><span class="pre">__qualname__</span></code>, <code class="docutils literal"><span class="pre">__annotations__</span></code> and <code class="docutils literal"><span class="pre">__doc__</span></code>, the documentation string) and <code class="docutils literal"><span class="pre">WRAPPER_UPDATES</span></code> (which updates the wrapper functions <code class="docutils literal"><span class="pre">__dict__</span></code>, i.e. </span><span class="yiyi-st" id="yiyi-94">实例的字典).</span></p><p><span class="yiyi-st" id="yiyi-95">为了允许访问原始功能以进行内省和其他目的(例如,</span><span class="yiyi-st" id="yiyi-96">绕过缓存装饰器(例如<a class="reference internal" href="#functools.lru_cache" title="functools.lru_cache"><code class="xref py py-func docutils literal"><span class="pre">lru_cache()</span></code></a>),此函数会自动向包装器添加一个<code class="docutils literal"><span class="pre">__wrapped__</span></code>属性,该属性引用要包装的函数。</span></p><p><span class="yiyi-st" id="yiyi-97">此函数的主要用途是在<a class="reference internal" href="../glossary.html#term-decorator"><span class="xref std std-term">decorator</span></a>函数中,它包装修饰的函数并返回包装器。</span><span class="yiyi-st" id="yiyi-98">如果不更新包装器函数,返回的函数的元数据将反射包装器的定义,而不是原函数的定义 ,这通常是没有意义的。</span></p><p><span class="yiyi-st" id="yiyi-99"><a class="reference internal" href="#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal"><span class="pre">update_wrapper()</span></code></a>可以与除函数之外的可调用项一起使用。</span><span class="yiyi-st" id="yiyi-100">忽略<em>分配的</em><em>更新</em>中指定的任何属性,这些属性从正在包装的对象中丢失。</span><span class="yiyi-st" id="yiyi-101">此函数不会尝试在包装函数中设置它们)。</span><span class="yiyi-st" id="yiyi-102">如果包装函数本身缺少在<em>更新的</em>中命名的任何属性,则仍会引发<a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal"><span class="pre">AttributeError</span></code></a></span></p><div class="versionadded"><p><span class="yiyi-st" id="yiyi-103"><span class="versionmodified">版本3.2中的新功能:</span>自动添加<code class="docutils literal"><span class="pre">__wrapped__</span></code>属性。</span></p></div><div class="versionadded"><p><span class="yiyi-st" id="yiyi-104"><span class="versionmodified">版本3.2中的新功能:</span>默认情况下复制<code class="docutils literal"><span class="pre">__annotations__</span></code>属性。</span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-105"><span class="versionmodified">在版本3.2中更改:</span>缺少的属性不再触发<a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal"><span class="pre">AttributeError</span></code></a></span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-106"><span class="versionmodified">在版本3.4中更改:</span> <code class="docutils literal"><span class="pre">__wrapped__</span></code>属性现在总是引用wrapped函数即使该函数定义了<code class="docutils literal"><span class="pre">__wrapped__</span></code>属性。</span><span class="yiyi-st" id="yiyi-107">(参见<a class="reference external" href="https://bugs.python.org/issue17482">问题17482</a></span></p></div></dd></dl><dl class="function"><dt id="functools.wraps"><span class="yiyi-st" id="yiyi-108"><code class="descclassname">@</code><code class="descclassname">functools.</code><code class="descname">wraps</code><span class="sig-paren">(</span><em>wrapped</em>, <em>assigned=WRAPPER_ASSIGNMENTS</em>, <em>updated=WRAPPER_UPDATES</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-109">这是一个方便的函数,用于在定义包装器函数时调用<a class="reference internal" href="#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal"><span class="pre">update_wrapper()</span></code></a>作为函数装饰器。</span><span class="yiyi-st" id="yiyi-110">它等效于<code class="docutils literal"><span class="pre">partialupdate_wrapper</span> <span class="pre">wrapped = wrapped</span> <span class="pre">assigned = assigned</span> <span class="pre">updated = updated t4 &gt;</span></code></span><span class="yiyi-st" id="yiyi-111">示例:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">wraps</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">my_decorator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="gp">... </span> <span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">):</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">'Calling decorated function'</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwds</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">wrapper</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nd">@my_decorator</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">example</span><span class="p">():</span>
<span class="gp">... </span> <span class="sd">"""Docstring"""</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">'Called example function'</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">example</span><span class="p">()</span>
<span class="go">Calling decorated function</span>
<span class="go">Called example function</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">example</span><span class="o">.</span><span class="n">__name__</span>
<span class="go">'example'</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">example</span><span class="o">.</span><span class="n">__doc__</span>
<span class="go">'Docstring'</span>
</code></pre><p><span class="yiyi-st" id="yiyi-112">没有使用这个装饰器工厂,示例函数的名称将是<code class="docutils literal"><span class="pre">'wrapper'</span></code>,原始<code class="xref py py-func docutils literal"><span class="pre">example()</span></code>的docstring将丢失。</span></p></dd></dl><div class="section" id="partial-objects"><h2><span class="yiyi-st" id="yiyi-113">10.2.1. <a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象</span></h2><p><span class="yiyi-st" id="yiyi-114"><a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象是由<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal"><span class="pre">partial()</span></code></a>创建的可调用对象。</span><span class="yiyi-st" id="yiyi-115">它们有三个只读属性:</span></p><dl class="attribute"><dt id="functools.partial.func"><span class="yiyi-st" id="yiyi-116"><code class="descclassname">partial.</code><code class="descname">func</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-117">一个可调用对象或函数。</span><span class="yiyi-st" id="yiyi-118"><a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象的调用将使用新的参数和关键字转发到<a class="reference internal" href="#functools.partial.func" title="functools.partial.func"><code class="xref py py-attr docutils literal"><span class="pre">func</span></code></a></span></p></dd></dl><dl class="attribute"><dt id="functools.partial.args"><span class="yiyi-st" id="yiyi-119"><code class="descclassname">partial.</code><code class="descname">args</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-120">最左边的位置参数将被提供给提供给<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象调用的位置参数。</span></p></dd></dl><dl class="attribute"><dt id="functools.partial.keywords"><span class="yiyi-st" id="yiyi-121"><code class="descclassname">partial.</code><code class="descname">keywords</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-122">当调用<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象时将提供的关键字参数。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-123"><a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象类似于<code class="xref py py-class docutils literal"><span class="pre">function</span></code>对象,因为它们是可调用的,弱引用的,并且可以具有属性。</span><span class="yiyi-st" id="yiyi-124">它们有一些重要的区别。</span><span class="yiyi-st" id="yiyi-125">对于实例,不会自动创建<a class="reference internal" href="stdtypes.html#definition.__name__" title="definition.__name__"><code class="xref py py-attr docutils literal"><span class="pre">__name__</span></code></a><code class="xref py py-attr docutils literal"><span class="pre">__doc__</span></code>属性。</span><span class="yiyi-st" id="yiyi-126">此外,在类中定义的<a class="reference internal" href="#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal"><span class="pre">partial</span></code></a>对象的行为类似于静态方法,并且在实例属性查找期间不会转换为绑定的方法。</span></p></div></div></div>