[code.view]

[top] / python / PyMOTW / docs / functools / index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>functools – Tools for Manipulating Functions &mdash; Python Module of the Week</title>
    <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.132',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="top" title="Python Module of the Week" href="../index.html" />
    <link rel="up" title="Numeric and Mathematical Modules" href="../numeric.html" />
    <link rel="next" title="itertools – Iterator functions for efficient looping" href="../itertools/index.html" />
    <link rel="prev" title="fractions – Rational Numbers" href="../fractions/index.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../itertools/index.html" title="itertools – Iterator functions for efficient looping"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="../fractions/index.html" title="fractions – Rational Numbers"
             accesskey="P">previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../numeric.html" accesskey="U">Numeric and Mathematical Modules</a> &raquo;</li> 
      </ul>
    </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">functools &#8211; Tools for Manipulating Functions</a><ul>
<li><a class="reference internal" href="#decorators">Decorators</a><ul>
<li><a class="reference internal" href="#partial">partial</a></li>
<li><a class="reference internal" href="#update-wrapper">update_wrapper</a></li>
<li><a class="reference internal" href="#other-callables">Other Callables</a></li>
<li><a class="reference internal" href="#wraps">wraps</a></li>
</ul>
</li>
<li><a class="reference internal" href="#comparison">Comparison</a><ul>
<li><a class="reference internal" href="#rich-comparison">Rich Comparison</a></li>
<li><a class="reference internal" href="#collation-order">Collation Order</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="../fractions/index.html"
                        title="previous chapter">fractions &#8211; Rational Numbers</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="../itertools/index.html"
                        title="next chapter">itertools &#8211; Iterator functions for efficient looping</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/functools/index.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" size="18" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="module-functools">
<span id="functools-tools-for-manipulating-functions"></span><h1>functools &#8211; Tools for Manipulating Functions<a class="headerlink" href="#module-functools" title="Permalink to this headline">¶</a></h1>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Purpose:</th><td class="field-body">Functions that operate on other functions.</td>
</tr>
<tr class="field"><th class="field-name">Python Version:</th><td class="field-body">2.5 and later</td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="#module-functools" title="functools: Tools for working with functions."><tt class="xref py py-mod docutils literal"><span class="pre">functools</span></tt></a> module provides tools for working with functions
and other callable objects, to adapt or extend them for new purposes
without completely rewriting them.</p>
<div class="section" id="decorators">
<h2>Decorators<a class="headerlink" href="#decorators" title="Permalink to this headline">¶</a></h2>
<p>The primary tool supplied by the <a class="reference internal" href="#module-functools" title="functools: Tools for working with functions."><tt class="xref py py-mod docutils literal"><span class="pre">functools</span></tt></a> module is the class
<tt class="xref py py-class docutils literal"><span class="pre">partial</span></tt>, which can be used to &#8220;wrap&#8221; a callable object with
default arguments. The resulting object is itself callable, and can be
treated as though it is the original function.  It takes all of the
same arguments as the original, and can be invoked with extra
positional or named arguments as well.</p>
<div class="section" id="partial">
<h3>partial<a class="headerlink" href="#partial" title="Permalink to this headline">¶</a></h3>
<p>This example shows two simple <tt class="xref py py-class docutils literal"><span class="pre">partial</span></tt> objects for the
function <tt class="xref py py-func docutils literal"><span class="pre">myfunc()</span></tt>.  Notice that <tt class="xref py py-func docutils literal"><span class="pre">show_details()</span></tt> prints the
<tt class="xref py py-attr docutils literal"><span class="pre">func</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">args</span></tt>, and <tt class="xref py py-attr docutils literal"><span class="pre">keywords</span></tt> attributes of the
partial object.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>

<span class="k">def</span> <span class="nf">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Docstring for myfunc().&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">called myfunc with:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
    <span class="k">return</span>

<span class="k">def</span> <span class="nf">show_details</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">is_partial</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Show details of a callable object.&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">name</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">object:&#39;</span><span class="p">,</span> <span class="n">f</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">is_partial</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__name__:&#39;</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">__name__</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__doc__&#39;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">__doc__</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">is_partial</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">func:&#39;</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">func</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">args:&#39;</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">args</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">keywords:&#39;</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">keywords</span>
    <span class="k">return</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;myfunc&#39;</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>
<span class="n">myfunc</span><span class="p">(</span><span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">p1</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">myfunc</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;partial with named default&#39;</span><span class="p">,</span> <span class="n">p1</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
<span class="n">p1</span><span class="p">(</span><span class="s">&#39;default a&#39;</span><span class="p">)</span>
<span class="n">p1</span><span class="p">(</span><span class="s">&#39;override b&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">p2</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">myfunc</span><span class="p">,</span> <span class="s">&#39;default a&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;partial with defaults&#39;</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
<span class="n">p2</span><span class="p">()</span>
<span class="n">p2</span><span class="p">(</span><span class="n">b</span><span class="o">=</span><span class="s">&#39;override b&#39;</span><span class="p">)</span>
<span class="k">print</span>

<span class="k">print</span> <span class="s">&#39;Insufficient arguments:&#39;</span>
<span class="n">p1</span><span class="p">()</span>
</pre></div>
</div>
<p>At the end of the example, the first <tt class="xref py py-class docutils literal"><span class="pre">partial</span></tt> created is
invoked without passing a value for <em>a</em>, causing an exception.</p>
<div class="highlight-python"><pre>$ python functools_partial.py

myfunc:
        object: &lt;function myfunc at 0x10045bf50&gt;
        __name__: myfunc
        __doc__ 'Docstring for myfunc().'
        called myfunc with: ('a', 3)

partial with named default:
        object: &lt;functools.partial object at 0x1004583c0&gt;
        __doc__ 'partial(func, *args, **keywords) - new function with partial
 application\n    of the given arguments and keywords.\n'
        func: &lt;function myfunc at 0x10045bf50&gt;
        args: ()
        keywords: {'b': 4}
        called myfunc with: ('default a', 4)
        called myfunc with: ('override b', 5)

partial with defaults:
        object: &lt;functools.partial object at 0x100458418&gt;
        __doc__ 'partial(func, *args, **keywords) - new function with partial
 application\n    of the given arguments and keywords.\n'
        func: &lt;function myfunc at 0x10045bf50&gt;
        args: ('default a',)
        keywords: {'b': 99}
        called myfunc with: ('default a', 99)
        called myfunc with: ('default a', 'override b')

Insufficient arguments:
Traceback (most recent call last):
  File "functools_partial.py", line 49, in &lt;module&gt;
    p1()
TypeError: myfunc() takes at least 1 argument (1 given)</pre>
</div>
</div>
<div class="section" id="update-wrapper">
<h3>update_wrapper<a class="headerlink" href="#update-wrapper" title="Permalink to this headline">¶</a></h3>
<p>The partial object does not have <tt class="xref py py-attr docutils literal"><span class="pre">__name__</span></tt> or <tt class="xref py py-attr docutils literal"><span class="pre">__doc__</span></tt>
attributes by default, and without those attributes decorated
functions are more difficult to debug. Using <tt class="xref py py-func docutils literal"><span class="pre">update_wrapper()</span></tt>,
copies or adds attributes from the original function to the
<tt class="xref py py-class docutils literal"><span class="pre">partial</span></tt> object.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>

<span class="k">def</span> <span class="nf">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Docstring for myfunc().&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">called myfunc with:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
    <span class="k">return</span>

<span class="k">def</span> <span class="nf">show_details</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Show details of a callable object.&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">name</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">object:&#39;</span><span class="p">,</span> <span class="n">f</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__name__:&#39;</span><span class="p">,</span> 
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="n">f</span><span class="o">.</span><span class="n">__name__</span>
    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;(no __name__)&#39;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__doc__&#39;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">__doc__</span><span class="p">)</span>
    <span class="k">print</span>
    <span class="k">return</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;myfunc&#39;</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>

<span class="n">p1</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">myfunc</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;raw wrapper&#39;</span><span class="p">,</span> <span class="n">p1</span><span class="p">)</span>

<span class="k">print</span> <span class="s">&#39;Updating wrapper:&#39;</span>
<span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">assign:&#39;</span><span class="p">,</span> <span class="n">functools</span><span class="o">.</span><span class="n">WRAPPER_ASSIGNMENTS</span>
<span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">update:&#39;</span><span class="p">,</span> <span class="n">functools</span><span class="o">.</span><span class="n">WRAPPER_UPDATES</span>
<span class="k">print</span>

<span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;updated wrapper&#39;</span><span class="p">,</span> <span class="n">p1</span><span class="p">)</span>
</pre></div>
</div>
<p>The attributes added to the wrapper are defined in
<tt class="xref py py-const docutils literal"><span class="pre">functools.WRAPPER_ASSIGNMENTS</span></tt>, while
<tt class="xref py py-const docutils literal"><span class="pre">functools.WRAPPER_UPDATES</span></tt> lists values to be modified.</p>
<div class="highlight-python"><pre>$ python functools_update_wrapper.py

myfunc:
        object: &lt;function myfunc at 0x100462050&gt;
        __name__: myfunc
        __doc__ 'Docstring for myfunc().'

raw wrapper:
        object: &lt;functools.partial object at 0x100458418&gt;
        __name__: (no __name__)
        __doc__ 'partial(func, *args, **keywords) - new function with partial
 application\n    of the given arguments and keywords.\n'

Updating wrapper:
        assign: ('__module__', '__name__', '__doc__')
        update: ('__dict__',)

updated wrapper:
        object: &lt;functools.partial object at 0x100458418&gt;
        __name__: myfunc
        __doc__ 'Docstring for myfunc().'</pre>
</div>
</div>
<div class="section" id="other-callables">
<h3>Other Callables<a class="headerlink" href="#other-callables" title="Permalink to this headline">¶</a></h3>
<p>Partials work with any callable object, not just standalone functions.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>

<span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Demonstration class for functools&quot;&quot;&quot;</span>
    
    <span class="k">def</span> <span class="nf">meth1</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Docstring for meth1().&quot;&quot;&quot;</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">called meth1 with:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
        <span class="k">return</span>
    
    <span class="k">def</span> <span class="nf">meth2</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Docstring for meth2&quot;&quot;&quot;</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">called meth2 with:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="k">return</span>
    <span class="n">wrapped_meth2</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">meth2</span><span class="p">,</span> <span class="s">&#39;wrapped c&#39;</span><span class="p">)</span>
    <span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="n">wrapped_meth2</span><span class="p">,</span> <span class="n">meth2</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="o">=</span><span class="mi">6</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Docstring for MyClass.__call__&quot;&quot;&quot;</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">called object with:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
        <span class="k">return</span>

<span class="k">def</span> <span class="nf">show_details</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Show details of a callable object.&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">name</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">object:&#39;</span><span class="p">,</span> <span class="n">f</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__name__:&#39;</span><span class="p">,</span> 
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="n">f</span><span class="o">.</span><span class="n">__name__</span>
    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;(no __name__)&#39;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__doc__&#39;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">__doc__</span><span class="p">)</span>
    <span class="k">return</span>
    
<span class="n">o</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;meth1 straight&#39;</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">meth1</span><span class="p">)</span>
<span class="n">o</span><span class="o">.</span><span class="n">meth1</span><span class="p">(</span><span class="s">&#39;no default for a&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">p1</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">o</span><span class="o">.</span><span class="n">meth1</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
<span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">meth1</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;meth1 wrapper&#39;</span><span class="p">,</span> <span class="n">p1</span><span class="p">)</span>
<span class="n">p1</span><span class="p">(</span><span class="s">&#39;a goes here&#39;</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;meth2&#39;</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">meth2</span><span class="p">)</span>
<span class="n">o</span><span class="o">.</span><span class="n">meth2</span><span class="p">(</span><span class="s">&#39;no default for c&#39;</span><span class="p">,</span> <span class="n">d</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;wrapped meth2&#39;</span><span class="p">,</span> <span class="n">o</span><span class="o">.</span><span class="n">wrapped_meth2</span><span class="p">)</span>
<span class="n">o</span><span class="o">.</span><span class="n">wrapped_meth2</span><span class="p">(</span><span class="s">&#39;no default for c&#39;</span><span class="p">,</span> <span class="n">d</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;instance&#39;</span><span class="p">,</span> <span class="n">o</span><span class="p">)</span>
<span class="n">o</span><span class="p">(</span><span class="s">&#39;no default for e&#39;</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">p2</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">f</span><span class="o">=</span><span class="mi">7</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;instance wrapper&#39;</span><span class="p">,</span> <span class="n">p2</span><span class="p">)</span>
<span class="n">p2</span><span class="p">(</span><span class="s">&#39;e goes here&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>This example creates partials from an instance, and methods of an
instance.</p>
<div class="highlight-python"><pre>$ python functools_method.py

meth1 straight:
        object: &lt;bound method MyClass.meth1 of &lt;__main__.MyClass object at
0x100463550&gt;&gt;
        __name__: meth1
        __doc__ 'Docstring for meth1().'
        called meth1 with: (&lt;__main__.MyClass object at 0x100463550&gt;, 'no d
efault for a', 3)

meth1 wrapper:
        object: &lt;functools.partial object at 0x1004584c8&gt;
        __name__: meth1
        __doc__ 'Docstring for meth1().'
        called meth1 with: (&lt;__main__.MyClass object at 0x100463550&gt;, 'a go
es here', 4)

meth2:
        object: &lt;bound method MyClass.meth2 of &lt;__main__.MyClass object at
0x100463550&gt;&gt;
        __name__: meth2
        __doc__ 'Docstring for meth2'
        called meth2 with: (&lt;__main__.MyClass object at 0x100463550&gt;, 'no d
efault for c', 6)

wrapped meth2:
        object: &lt;functools.partial object at 0x100458418&gt;
        __name__: meth2
        __doc__ 'Docstring for meth2'
        called meth2 with: ('wrapped c', 'no default for c', 6)

instance:
        object: &lt;__main__.MyClass object at 0x100463550&gt;
        __name__: (no __name__)
        __doc__ 'Demonstration class for functools'
        called object with: (&lt;__main__.MyClass object at 0x100463550&gt;, 'no
default for e', 6)

instance wrapper:
        object: &lt;functools.partial object at 0x100458520&gt;
        __name__: (no __name__)
        __doc__ 'partial(func, *args, **keywords) - new function with parti
al application\n    of the given arguments and keywords.\n'
        called object with: (&lt;__main__.MyClass object at 0x100463550&gt;, 'e g
oes here', 7)</pre>
</div>
</div>
<div class="section" id="wraps">
<h3>wraps<a class="headerlink" href="#wraps" title="Permalink to this headline">¶</a></h3>
<p>Updating the properties of a wrapped callable is especially useful
when used in a decorator, since the transformed function ends up with
properties of the original, &#8220;bare&#8221;, function.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>

<span class="k">def</span> <span class="nf">show_details</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Show details of a callable object.&quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">name</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">object:&#39;</span><span class="p">,</span> <span class="n">f</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__name__:&#39;</span><span class="p">,</span> 
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="n">f</span><span class="o">.</span><span class="n">__name__</span>
    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;(no __name__)&#39;</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">__doc__&#39;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">__doc__</span><span class="p">)</span>
    <span class="k">print</span>
    <span class="k">return</span>

<span class="k">def</span> <span class="nf">simple_decorator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
    <span class="nd">@functools.wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">decorated</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="s">&#39;decorated defaults&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">decorated:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
        <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">&#39;</span><span class="p">,</span>
        <span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="n">b</span><span class="p">)</span>
        <span class="k">return</span>
    <span class="k">return</span> <span class="n">decorated</span>

<span class="k">def</span> <span class="nf">myfunc</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\t</span><span class="s">myfunc:&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)</span>
    <span class="k">return</span>

<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;myfunc&#39;</span><span class="p">,</span> <span class="n">myfunc</span><span class="p">)</span>
<span class="n">myfunc</span><span class="p">(</span><span class="s">&#39;unwrapped, default b&#39;</span><span class="p">)</span>
<span class="n">myfunc</span><span class="p">(</span><span class="s">&#39;unwrapped, passing b&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="k">print</span>

<span class="n">wrapped_myfunc</span> <span class="o">=</span> <span class="n">simple_decorator</span><span class="p">(</span><span class="n">myfunc</span><span class="p">)</span>
<span class="n">show_details</span><span class="p">(</span><span class="s">&#39;wrapped_myfunc&#39;</span><span class="p">,</span> <span class="n">wrapped_myfunc</span><span class="p">)</span>
<span class="n">wrapped_myfunc</span><span class="p">()</span>
<span class="n">wrapped_myfunc</span><span class="p">(</span><span class="s">&#39;args to decorated&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p><a class="reference internal" href="#module-functools" title="functools: Tools for working with functions."><tt class="xref py py-mod docutils literal"><span class="pre">functools</span></tt></a> provides a decorator, <tt class="xref py py-func docutils literal"><span class="pre">wraps()</span></tt>, which applies
<tt class="xref py py-func docutils literal"><span class="pre">update_wrapper()</span></tt> to the decorated function.</p>
<div class="highlight-python"><pre>$ python functools_wraps.py

myfunc:
        object: &lt;function myfunc at 0x100464488&gt;
        __name__: myfunc
        __doc__ None

        myfunc: ('unwrapped, default b', 2)
        myfunc: ('unwrapped, passing b', 3)

wrapped_myfunc:
        object: &lt;function myfunc at 0x100464500&gt;
        __name__: myfunc
        __doc__ None

        decorated: ('decorated defaults', 1)
                myfunc: ('decorated defaults', 1)
        decorated: ('args to decorated', 4)
                myfunc: ('args to decorated', 4)</pre>
</div>
</div>
</div>
<div class="section" id="comparison">
<h2>Comparison<a class="headerlink" href="#comparison" title="Permalink to this headline">¶</a></h2>
<p>Under Python 2, classes can define a <tt class="xref py py-func docutils literal"><span class="pre">__cmp__()</span></tt> method that
returns <tt class="docutils literal"><span class="pre">-1</span></tt>, <tt class="docutils literal"><span class="pre">0</span></tt>, or <tt class="docutils literal"><span class="pre">1</span></tt> based on whether the object is less
than, equal to, or greater than the item being compared.  Python 2.1
introduces the <em>rich comparison</em> methods API, <tt class="xref py py-func docutils literal"><span class="pre">__lt__()</span></tt>,
<tt class="xref py py-func docutils literal"><span class="pre">__le__()</span></tt>, <tt class="xref py py-func docutils literal"><span class="pre">__eq__()</span></tt>, <tt class="xref py py-func docutils literal"><span class="pre">__ne__()</span></tt>, <tt class="xref py py-func docutils literal"><span class="pre">__gt__()</span></tt>, and
<tt class="xref py py-func docutils literal"><span class="pre">__ge__()</span></tt>, which perform a single comparison operation and return
a boolean value.  Python 3 deprecated <tt class="xref py py-func docutils literal"><span class="pre">__cmp__()</span></tt> in favor of
these new methods, so <a class="reference internal" href="#module-functools" title="functools: Tools for working with functions."><tt class="xref py py-mod docutils literal"><span class="pre">functools</span></tt></a> provides tools to make it
easier to write Python 2 classes that comply with the new comparison
requirements in Python 3.</p>
<div class="section" id="rich-comparison">
<h3>Rich Comparison<a class="headerlink" href="#rich-comparison" title="Permalink to this headline">¶</a></h3>
<p>The rich comparison API is designed to allow classes with complex
comparisons to implement each test in the most efficient way possible.
However, for classes where comparison is relatively simple, there is
no point in manually creating each of the rich comparison methods.
The <tt class="xref py py-func docutils literal"><span class="pre">total_ordering()</span></tt> class decorator takes a class that provides
some of the methods, and adds the rest of them.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>
<span class="kn">import</span> <span class="nn">inspect</span>
<span class="kn">from</span> <span class="nn">pprint</span> <span class="kn">import</span> <span class="n">pprint</span>

<span class="nd">@functools.total_ordering</span>
<span class="k">class</span> <span class="nc">MyObject</span><span class="p">(</span><span class="nb">object</span><span class="p">):</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="n">val</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">val</span> <span class="o">=</span> <span class="n">val</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">print</span> <span class="s">&#39;  testing __eq__(</span><span class="si">%s</span><span class="s">, </span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">val</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">val</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">val</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">val</span>
    <span class="k">def</span> <span class="nf">__gt__</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">print</span> <span class="s">&#39;  testing __gt__(</span><span class="si">%s</span><span class="s">, </span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">val</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">val</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">val</span> <span class="o">&gt;</span> <span class="n">other</span><span class="o">.</span><span class="n">val</span>

<span class="k">print</span> <span class="s">&#39;Methods:</span><span class="se">\n</span><span class="s">&#39;</span>
<span class="n">pprint</span><span class="p">(</span><span class="n">inspect</span><span class="o">.</span><span class="n">getmembers</span><span class="p">(</span><span class="n">MyObject</span><span class="p">,</span> <span class="n">inspect</span><span class="o">.</span><span class="n">ismethod</span><span class="p">))</span>

<span class="n">a</span> <span class="o">=</span> <span class="n">MyObject</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">MyObject</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>

<span class="k">print</span> <span class="s">&#39;</span><span class="se">\n</span><span class="s">Comparisons:&#39;</span>
<span class="k">for</span> <span class="n">expr</span> <span class="ow">in</span> <span class="p">[</span> <span class="s">&#39;a &lt; b&#39;</span><span class="p">,</span> <span class="s">&#39;a &lt;= b&#39;</span><span class="p">,</span> <span class="s">&#39;a == b&#39;</span><span class="p">,</span> <span class="s">&#39;a &gt;= b&#39;</span><span class="p">,</span> <span class="s">&#39;a &gt; b&#39;</span> <span class="p">]:</span>
    <span class="k">print</span> <span class="s">&#39;</span><span class="se">\n</span><span class="si">%-6s</span><span class="s">:&#39;</span> <span class="o">%</span> <span class="n">expr</span>
    <span class="n">result</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">expr</span><span class="p">)</span>
    <span class="k">print</span> <span class="s">&#39;  result of </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">expr</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
</pre></div>
</div>
<p>The class must provide an implmentation of <tt class="xref py py-func docutils literal"><span class="pre">__eq__()</span></tt> and any one
of the other rich comparison methods.  The decorator adds
implementations of the other methods that work by using the
comparisons provided.</p>
<div class="highlight-python"><pre>$ python functools_total_ordering.py

Methods:

[('__eq__', &lt;unbound method MyObject.__eq__&gt;),
 ('__ge__', &lt;unbound method MyObject.__ge__&gt;),
 ('__gt__', &lt;unbound method MyObject.__gt__&gt;),
 ('__init__', &lt;unbound method MyObject.__init__&gt;),
 ('__le__', &lt;unbound method MyObject.__le__&gt;),
 ('__lt__', &lt;unbound method MyObject.__lt__&gt;)]

Comparisons:

a &lt; b :
  testing __gt__(2, 1)
  result of a &lt; b: True

a &lt;= b:
  testing __gt__(1, 2)
  result of a &lt;= b: True

a == b:
  testing __eq__(1, 2)
  result of a == b: False

a &gt;= b:
  testing __gt__(2, 1)
  result of a &gt;= b: False

a &gt; b :
  testing __gt__(1, 2)
  result of a &gt; b: False</pre>
</div>
</div>
<div class="section" id="collation-order">
<h3>Collation Order<a class="headerlink" href="#collation-order" title="Permalink to this headline">¶</a></h3>
<p>Since old-style comparison functions are deprecated in Python 3, the
<tt class="xref py py-data docutils literal"><span class="pre">cmp</span></tt> argument to functions like <tt class="xref py py-func docutils literal"><span class="pre">sort()</span></tt> are also no longer
supported.  Python 2 programs that use comparison functions can use
<tt class="xref py py-func docutils literal"><span class="pre">cmp_to_key()</span></tt> to convert them to a function that returns a
<em>collation key</em>, which is used to determine the position in the final
sequence.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>

<span class="k">class</span> <span class="nc">MyObject</span><span class="p">(</span><span class="nb">object</span><span class="p">):</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="n">val</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">val</span> <span class="o">=</span> <span class="n">val</span>
    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&#39;MyObject(</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">val</span>

<span class="k">def</span> <span class="nf">compare_obj</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Old-style comparison function.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">print</span> <span class="s">&#39;comparing </span><span class="si">%s</span><span class="s"> and </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
    <span class="k">return</span> <span class="nb">cmp</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">val</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">val</span><span class="p">)</span>

<span class="c"># Make a key function using cmp_to_key()</span>
<span class="n">get_key</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">cmp_to_key</span><span class="p">(</span><span class="n">compare_obj</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">get_key_wrapper</span><span class="p">(</span><span class="n">o</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Wrapper function for get_key to allow for print statements.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">new_key</span> <span class="o">=</span> <span class="n">get_key</span><span class="p">(</span><span class="n">o</span><span class="p">)</span>
    <span class="k">print</span> <span class="s">&#39;key_wrapper(</span><span class="si">%s</span><span class="s">) -&gt; </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">new_key</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">new_key</span>
        
<span class="n">objs</span> <span class="o">=</span> <span class="p">[</span> <span class="n">MyObject</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">]</span>

<span class="k">for</span> <span class="n">o</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">objs</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">get_key_wrapper</span><span class="p">):</span>
    <span class="k">print</span> <span class="n">o</span>
    
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Normally <tt class="xref py py-func docutils literal"><span class="pre">cmp_to_key()</span></tt> would be used directly, but in this
example an extra wrapper function is introduced to print out more
information as the key function is being called.</p>
</div>
<p>The output shows that <tt class="xref py py-func docutils literal"><span class="pre">sorted()</span></tt> starts by calling
<tt class="xref py py-func docutils literal"><span class="pre">get_key_wrapper()</span></tt> for each item in the sequence to produce a
key.  The keys returned by <tt class="xref py py-func docutils literal"><span class="pre">cmp_to_key()</span></tt> are instances of a class
defined in <a class="reference internal" href="#module-functools" title="functools: Tools for working with functions."><tt class="xref py py-mod docutils literal"><span class="pre">functools</span></tt></a> that implements the rich comparison API
based on the return value of the provided old-style comparison
function.  After all of the keys are created, the sequence is sorted
by comparing the keys.</p>
<div class="highlight-python"><pre>$ python functools_cmp_to_key.py

key_wrapper(MyObject(5)) -&gt; &lt;functools.K object at 0x100462a90&gt;
key_wrapper(MyObject(4)) -&gt; &lt;functools.K object at 0x100462ad0&gt;
key_wrapper(MyObject(3)) -&gt; &lt;functools.K object at 0x100462b10&gt;
key_wrapper(MyObject(2)) -&gt; &lt;functools.K object at 0x100462b50&gt;
key_wrapper(MyObject(1)) -&gt; &lt;functools.K object at 0x100462b90&gt;
comparing MyObject(4) and MyObject(5)
comparing MyObject(3) and MyObject(4)
comparing MyObject(2) and MyObject(3)
comparing MyObject(1) and MyObject(2)
MyObject(1)
MyObject(2)
MyObject(3)
MyObject(4)
MyObject(5)</pre>
</div>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference external" href="http://docs.python.org/library/functools.html">functools</a></dt>
<dd>The standard library documentation for this module.</dd>
<dt><a class="reference external" href="http://docs.python.org/reference/datamodel.html#object.__lt__">Rich comparison methods</a></dt>
<dd>Description of the rich comparison methods from the Python Reference Guide.</dd>
</dl>
</div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../itertools/index.html" title="itertools – Iterator functions for efficient looping"
             >next</a> |</li>
        <li class="right" >
          <a href="../fractions/index.html" title="fractions – Rational Numbers"
             >previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../numeric.html" >Numeric and Mathematical Modules</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; Copyright Doug Hellmann.
      Last updated on Oct 24, 2010.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.

    <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a>
    
    </div>
  </body>
</html>

[top] / python / PyMOTW / docs / functools / index.html

contact | logmethods.com