mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
163 lines
56 KiB
HTML
163 lines
56 KiB
HTML
<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">>>></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">>>></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"><</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">>>></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">>>></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"><</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">>>> </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">partial</span>
|
||
<span class="gp">>>> </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">>>> </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">>>> </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>提供给<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">>>> </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">>>> </span><span class="n">c</span> <span class="o">=</span> <span class="n">Cell</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">c</span><span class="o">.</span><span class="n">alive</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">c</span><span class="o">.</span><span class="n">set_alive</span><span class="p">()</span>
|
||
<span class="gp">>>> </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">>>> </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">singledispatch</span>
|
||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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"><function fun_num at 0x1035a2840></span>
|
||
<span class="gp">>>> </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"><function fun at 0x103fe0000></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">>>> </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([<class 'NoneType'>, <class 'int'>, <class 'object'>,</span>
|
||
<span class="go"> <class 'decimal.Decimal'>, <class 'list'>,</span>
|
||
<span class="go"> <class 'float'>])</span>
|
||
<span class="gp">>>> </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"><function fun_num at 0x1035a2840></span>
|
||
<span class="gp">>>> </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"><function fun at 0x103fe0000></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 function’s <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 function’s <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">partial(update_wrapper,</span> <span class="pre">wrapped = wrapped,</span> <span class="pre">assigned = assigned,</span> <span class="pre">updated = updated) t4 ></span></code>。</span><span class="yiyi-st" id="yiyi-111">示例:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">functools</span> <span class="k">import</span> <span class="n">wraps</span>
|
||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </span><span class="n">example</span><span class="o">.</span><span class="n">__name__</span>
|
||
<span class="go">'example'</span>
|
||
<span class="gp">>>> </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> |