CINXE.COM
PEP 362 – Function Signature Object | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 362 – Function Signature Object | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0362/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 362 – Function Signature Object | peps.python.org'> <meta property="og:description" content="Python has always supported powerful introspection capabilities, including introspecting functions and methods (for the rest of this PEP, “function” refers to both functions and methods). By examining a function object you can fully reconstruct the fun..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0362/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="Python has always supported powerful introspection capabilities, including introspecting functions and methods (for the rest of this PEP, “function” refers to both functions and methods). By examining a function object you can fully reconstruct the fun..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 362</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 362 – Function Signature Object</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Brett Cannon <brett at python.org>, Jiwon Seo <seojiwon at gmail.com>, Yury Selivanov <yury at edgedb.com>, Larry Hastings <larry at hastings.org></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">21-Aug-2006</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.3</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">04-Jun-2012</dd> <dt class="field-odd">Resolution<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2012-June/120682.html">Python-Dev message</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#signature-object">Signature Object</a></li> <li><a class="reference internal" href="#parameter-object">Parameter Object</a></li> <li><a class="reference internal" href="#boundarguments-object">BoundArguments Object</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#design-considerations">Design Considerations</a><ul> <li><a class="reference internal" href="#no-implicit-caching-of-signature-objects">No implicit caching of Signature objects</a></li> <li><a class="reference internal" href="#some-functions-may-not-be-introspectable">Some functions may not be introspectable</a></li> <li><a class="reference internal" href="#signature-and-parameter-equivalence">Signature and Parameter equivalence</a></li> </ul> </li> <li><a class="reference internal" href="#examples">Examples</a><ul> <li><a class="reference internal" href="#visualizing-callable-objects-signature">Visualizing Callable Objects’ Signature</a></li> <li><a class="reference internal" href="#annotation-checker">Annotation Checker</a></li> </ul> </li> <li><a class="reference internal" href="#acceptance">Acceptance</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>Python has always supported powerful introspection capabilities, including introspecting functions and methods (for the rest of this PEP, “function” refers to both functions and methods). By examining a function object you can fully reconstruct the function’s signature. Unfortunately this information is stored in an inconvenient manner, and is spread across a half-dozen deeply nested attributes.</p> <p>This PEP proposes a new representation for function signatures. The new representation contains all necessary information about a function and its parameters, and makes introspection easy and straightforward.</p> <p>However, this object does not replace the existing function metadata, which is used by Python itself to execute those functions. The new metadata object is intended solely to make function introspection easier for Python programmers.</p> </section> <section id="signature-object"> <h2><a class="toc-backref" href="#signature-object" role="doc-backlink">Signature Object</a></h2> <p>A Signature object represents the call signature of a function and its return annotation. For each parameter accepted by the function it stores a <a class="reference internal" href="#parameter-object">Parameter object</a> in its <code class="docutils literal notranslate"><span class="pre">parameters</span></code> collection.</p> <p>A Signature object has the following public attributes and methods:</p> <ul> <li><dl class="simple"> <dt>return_annotation : object</dt><dd>The “return” annotation for the function. If the function has no “return” annotation, this attribute is set to <code class="docutils literal notranslate"><span class="pre">Signature.empty</span></code>.</dd> </dl> </li> <li><dl class="simple"> <dt>parameters : OrderedDict</dt><dd>An ordered mapping of parameters’ names to the corresponding Parameter objects.</dd> </dl> </li> <li><dl class="simple"> <dt>bind(*args, **kwargs) -> BoundArguments</dt><dd>Creates a mapping from positional and keyword arguments to parameters. Raises a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if the passed arguments do not match the signature.</dd> </dl> </li> <li><dl class="simple"> <dt>bind_partial(*args, **kwargs) -> BoundArguments</dt><dd>Works the same way as <code class="docutils literal notranslate"><span class="pre">bind()</span></code>, but allows the omission of some required arguments (mimics <code class="docutils literal notranslate"><span class="pre">functools.partial</span></code> behavior.) Raises a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if the passed arguments do not match the signature.</dd> </dl> </li> <li><dl> <dt>replace(parameters=<optional>, *, return_annotation=<optional>) -> Signature</dt><dd>Creates a new Signature instance based on the instance <code class="docutils literal notranslate"><span class="pre">replace</span></code> was invoked on. It is possible to pass different <code class="docutils literal notranslate"><span class="pre">parameters</span></code> and/or <code class="docutils literal notranslate"><span class="pre">return_annotation</span></code> to override the corresponding properties of the base signature. To remove <code class="docutils literal notranslate"><span class="pre">return_annotation</span></code> from the copied <code class="docutils literal notranslate"><span class="pre">Signature</span></code>, pass in <code class="docutils literal notranslate"><span class="pre">Signature.empty</span></code>.<p>Note that the ‘=<optional>’ notation, means that the argument is optional. This notation applies to the rest of this PEP.</p> </dd> </dl> </li> </ul> <p>Signature objects are immutable. Use <code class="docutils literal notranslate"><span class="pre">Signature.replace()</span></code> to make a modified copy:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">foo</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span> <span class="gp">... </span> <span class="k">pass</span> <span class="gp">>>> </span><span class="n">sig</span> <span class="o">=</span> <span class="n">signature</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span> <span class="gp">>>> </span><span class="n">new_sig</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">return_annotation</span><span class="o">=</span><span class="s2">"new return annotation"</span><span class="p">)</span> <span class="gp">>>> </span><span class="n">new_sig</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">sig</span> <span class="go">True</span> <span class="gp">>>> </span><span class="n">new_sig</span><span class="o">.</span><span class="n">return_annotation</span> <span class="o">!=</span> <span class="n">sig</span><span class="o">.</span><span class="n">return_annotation</span> <span class="go">True</span> <span class="gp">>>> </span><span class="n">new_sig</span><span class="o">.</span><span class="n">parameters</span> <span class="o">==</span> <span class="n">sig</span><span class="o">.</span><span class="n">parameters</span> <span class="go">True</span> <span class="gp">>>> </span><span class="n">new_sig</span> <span class="o">=</span> <span class="n">new_sig</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">return_annotation</span><span class="o">=</span><span class="n">new_sig</span><span class="o">.</span><span class="n">empty</span><span class="p">)</span> <span class="gp">>>> </span><span class="n">new_sig</span><span class="o">.</span><span class="n">return_annotation</span> <span class="ow">is</span> <span class="n">Signature</span><span class="o">.</span><span class="n">empty</span> <span class="go">True</span> </pre></div> </div> <p>There are two ways to instantiate a Signature class:</p> <ul class="simple"> <li><dl class="simple"> <dt>Signature(parameters=<optional>, *, return_annotation=Signature.empty)</dt><dd>Default Signature constructor. Accepts an optional sequence of <code class="docutils literal notranslate"><span class="pre">Parameter</span></code> objects, and an optional <code class="docutils literal notranslate"><span class="pre">return_annotation</span></code>. Parameters sequence is validated to check that there are no parameters with duplicate names, and that the parameters are in the right order, i.e. positional-only first, then positional-or-keyword, etc.</dd> </dl> </li> <li><dl class="simple"> <dt>Signature.from_function(function)</dt><dd>Returns a Signature object reflecting the signature of the function passed in.</dd> </dl> </li> </ul> <p>It’s possible to test Signatures for equality. Two signatures are equal when their parameters are equal, their positional and positional-only parameters appear in the same order, and they have equal return annotations.</p> <p>Changes to the Signature object, or to any of its data members, do not affect the function itself.</p> <p>Signature also implements <code class="docutils literal notranslate"><span class="pre">__str__</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">Signature</span><span class="o">.</span><span class="n">from_function</span><span class="p">((</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="kc">None</span><span class="p">)))</span> <span class="go">'(*args)'</span> <span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">Signature</span><span class="p">())</span> <span class="go">'()'</span> </pre></div> </div> </section> <section id="parameter-object"> <h2><a class="toc-backref" href="#parameter-object" role="doc-backlink">Parameter Object</a></h2> <p>Python’s expressive syntax means functions can accept many different kinds of parameters with many subtle semantic differences. We propose a rich Parameter object designed to represent any possible function parameter.</p> <p>A Parameter object has the following public attributes and methods:</p> <ul> <li><dl class="simple"> <dt>name : str</dt><dd>The name of the parameter as a string. Must be a valid python identifier name (with the exception of <code class="docutils literal notranslate"><span class="pre">POSITIONAL_ONLY</span></code> parameters, which can have it set to <code class="docutils literal notranslate"><span class="pre">None</span></code>.)</dd> </dl> </li> <li><dl class="simple"> <dt>default : object</dt><dd>The default value for the parameter. If the parameter has no default value, this attribute is set to <code class="docutils literal notranslate"><span class="pre">Parameter.empty</span></code>.</dd> </dl> </li> <li><dl class="simple"> <dt>annotation : object</dt><dd>The annotation for the parameter. If the parameter has no annotation, this attribute is set to <code class="docutils literal notranslate"><span class="pre">Parameter.empty</span></code>.</dd> </dl> </li> <li><dl> <dt>kind</dt><dd>Describes how argument values are bound to the parameter. Possible values:<ul> <li><code class="docutils literal notranslate"><span class="pre">Parameter.POSITIONAL_ONLY</span></code> - value must be supplied as a positional argument.<p>Python has no explicit syntax for defining positional-only parameters, but many built-in and extension module functions (especially those that accept only one or two parameters) accept them.</p> </li> <li><code class="docutils literal notranslate"><span class="pre">Parameter.POSITIONAL_OR_KEYWORD</span></code> - value may be supplied as either a keyword or positional argument (this is the standard binding behaviour for functions implemented in Python.)</li> <li><code class="docutils literal notranslate"><span class="pre">Parameter.KEYWORD_ONLY</span></code> - value must be supplied as a keyword argument. Keyword only parameters are those which appear after a “*” or “*args” entry in a Python function definition.</li> <li><code class="docutils literal notranslate"><span class="pre">Parameter.VAR_POSITIONAL</span></code> - a tuple of positional arguments that aren’t bound to any other parameter. This corresponds to a “*args” parameter in a Python function definition.</li> <li><code class="docutils literal notranslate"><span class="pre">Parameter.VAR_KEYWORD</span></code> - a dict of keyword arguments that aren’t bound to any other parameter. This corresponds to a “**kwargs” parameter in a Python function definition.</li> </ul> <p>Always use <code class="docutils literal notranslate"><span class="pre">Parameter.*</span></code> constants for setting and checking value of the <code class="docutils literal notranslate"><span class="pre">kind</span></code> attribute.</p> </dd> </dl> </li> <li><dl class="simple"> <dt>replace(*, name=<optional>, kind=<optional>, default=<optional>, annotation=<optional>) -> Parameter</dt><dd>Creates a new Parameter instance based on the instance <code class="docutils literal notranslate"><span class="pre">replaced</span></code> was invoked on. To override a Parameter attribute, pass the corresponding argument. To remove an attribute from a <code class="docutils literal notranslate"><span class="pre">Parameter</span></code>, pass <code class="docutils literal notranslate"><span class="pre">Parameter.empty</span></code>.</dd> </dl> </li> </ul> <p>Parameter constructor:</p> <ul class="simple"> <li><dl class="simple"> <dt>Parameter(name, kind, *, annotation=Parameter.empty, default=Parameter.empty)</dt><dd>Instantiates a Parameter object. <code class="docutils literal notranslate"><span class="pre">name</span></code> and <code class="docutils literal notranslate"><span class="pre">kind</span></code> are required, while <code class="docutils literal notranslate"><span class="pre">annotation</span></code> and <code class="docutils literal notranslate"><span class="pre">default</span></code> are optional.</dd> </dl> </li> </ul> <p>Two parameters are equal when they have equal names, kinds, defaults, and annotations.</p> <p>Parameter objects are immutable. Instead of modifying a Parameter object, you can use <code class="docutils literal notranslate"><span class="pre">Parameter.replace()</span></code> to create a modified copy like so:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">param</span> <span class="o">=</span> <span class="n">Parameter</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="n">Parameter</span><span class="o">.</span><span class="n">KEYWORD_ONLY</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span> <span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">param</span><span class="p">)</span> <span class="go">'foo=42'</span> <span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">replace</span><span class="p">())</span> <span class="go">'foo=42'</span> <span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="n">Parameter</span><span class="o">.</span><span class="n">empty</span><span class="p">,</span> <span class="n">annotation</span><span class="o">=</span><span class="s1">'spam'</span><span class="p">))</span> <span class="go">"foo:'spam'"</span> </pre></div> </div> </section> <section id="boundarguments-object"> <h2><a class="toc-backref" href="#boundarguments-object" role="doc-backlink">BoundArguments Object</a></h2> <p>Result of a <code class="docutils literal notranslate"><span class="pre">Signature.bind</span></code> call. Holds the mapping of arguments to the function’s parameters.</p> <p>Has the following public attributes:</p> <ul class="simple"> <li><dl class="simple"> <dt>arguments : OrderedDict</dt><dd>An ordered, mutable mapping of parameters’ names to arguments’ values. Contains only explicitly bound arguments. Arguments for which <code class="docutils literal notranslate"><span class="pre">bind()</span></code> relied on a default value are skipped.</dd> </dl> </li> <li><dl class="simple"> <dt>args : tuple</dt><dd>Tuple of positional arguments values. Dynamically computed from the ‘arguments’ attribute.</dd> </dl> </li> <li><dl class="simple"> <dt>kwargs : dict</dt><dd>Dict of keyword arguments values. Dynamically computed from the ‘arguments’ attribute.</dd> </dl> </li> </ul> <p>The <code class="docutils literal notranslate"><span class="pre">arguments</span></code> attribute should be used in conjunction with <code class="docutils literal notranslate"><span class="pre">Signature.parameters</span></code> for any arguments processing purposes.</p> <p><code class="docutils literal notranslate"><span class="pre">args</span></code> and <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> properties can be used to invoke functions:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span> <span class="o">...</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">signature</span><span class="p">(</span><span class="n">test</span><span class="p">)</span> <span class="n">ba</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span> <span class="n">test</span><span class="p">(</span><span class="o">*</span><span class="n">ba</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">ba</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span> </pre></div> </div> <p>Arguments which could be passed as part of either <code class="docutils literal notranslate"><span class="pre">*args</span></code> or <code class="docutils literal notranslate"><span class="pre">**kwargs</span></code> will be included only in the <code class="docutils literal notranslate"><span class="pre">BoundArguments.args</span></code> attribute. Consider the following example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">1</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="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span> <span class="k">pass</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">signature</span><span class="p">(</span><span class="n">test</span><span class="p">)</span> <span class="n">ba</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">13</span><span class="p">)</span> <span class="o">>>></span> <span class="n">ba</span><span class="o">.</span><span class="n">args</span> <span class="p">(</span><span class="mi">10</span><span class="p">,)</span> <span class="o">>>></span> <span class="n">ba</span><span class="o">.</span><span class="n">kwargs</span><span class="p">:</span> <span class="p">{</span><span class="s1">'c'</span><span class="p">:</span> <span class="mi">13</span><span class="p">}</span> </pre></div> </div> </section> <section id="implementation"> <h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2> <p>The implementation adds a new function <code class="docutils literal notranslate"><span class="pre">signature()</span></code> to the <code class="docutils literal notranslate"><span class="pre">inspect</span></code> module. The function is the preferred way of getting a <code class="docutils literal notranslate"><span class="pre">Signature</span></code> for a callable object.</p> <p>The function implements the following algorithm:</p> <ul class="simple"> <li>If the object is not callable - raise a TypeError</li> <li>If the object has a <code class="docutils literal notranslate"><span class="pre">__signature__</span></code> attribute and if it is not <code class="docutils literal notranslate"><span class="pre">None</span></code> - return it</li> <li>If it has a <code class="docutils literal notranslate"><span class="pre">__wrapped__</span></code> attribute, return <code class="docutils literal notranslate"><span class="pre">signature(object.__wrapped__)</span></code></li> <li>If the object is an instance of <code class="docutils literal notranslate"><span class="pre">FunctionType</span></code>, construct and return a new <code class="docutils literal notranslate"><span class="pre">Signature</span></code> for it</li> <li>If the object is a bound method, construct and return a new <code class="docutils literal notranslate"><span class="pre">Signature</span></code> object, with its first parameter (usually <code class="docutils literal notranslate"><span class="pre">self</span></code> or <code class="docutils literal notranslate"><span class="pre">cls</span></code>) removed. (<code class="docutils literal notranslate"><span class="pre">classmethod</span></code> and <code class="docutils literal notranslate"><span class="pre">staticmethod</span></code> are supported too. Since both are descriptors, the former returns a bound method, and the latter returns its wrapped function.)</li> <li>If the object is an instance of <code class="docutils literal notranslate"><span class="pre">functools.partial</span></code>, construct a new <code class="docutils literal notranslate"><span class="pre">Signature</span></code> from its <code class="docutils literal notranslate"><span class="pre">partial.func</span></code> attribute, and account for already bound <code class="docutils literal notranslate"><span class="pre">partial.args</span></code> and <code class="docutils literal notranslate"><span class="pre">partial.kwargs</span></code></li> <li>If the object is a class or metaclass:<ul> <li>If the object’s type has a <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method defined in its MRO, return a Signature for it</li> <li>If the object has a <code class="docutils literal notranslate"><span class="pre">__new__</span></code> method defined in its MRO, return a Signature object for it</li> <li>If the object has a <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method defined in its MRO, return a Signature object for it</li> </ul> </li> <li>Return <code class="docutils literal notranslate"><span class="pre">signature(object.__call__)</span></code></li> </ul> <p>Note that the <code class="docutils literal notranslate"><span class="pre">Signature</span></code> object is created in a lazy manner, and is not automatically cached. However, the user can manually cache a Signature by storing it in the <code class="docutils literal notranslate"><span class="pre">__signature__</span></code> attribute.</p> <p>An implementation for Python 3.3 can be found at <a class="footnote-reference brackets" href="#impl" id="id1">[1]</a>. The python issue tracking the patch is <a class="footnote-reference brackets" href="#issue" id="id2">[2]</a>.</p> </section> <section id="design-considerations"> <h2><a class="toc-backref" href="#design-considerations" role="doc-backlink">Design Considerations</a></h2> <section id="no-implicit-caching-of-signature-objects"> <h3><a class="toc-backref" href="#no-implicit-caching-of-signature-objects" role="doc-backlink">No implicit caching of Signature objects</a></h3> <p>The first PEP design had a provision for implicit caching of <code class="docutils literal notranslate"><span class="pre">Signature</span></code> objects in the <code class="docutils literal notranslate"><span class="pre">inspect.signature()</span></code> function. However, this has the following downsides:</p> <ul class="simple"> <li>If the <code class="docutils literal notranslate"><span class="pre">Signature</span></code> object is cached then any changes to the function it describes will not be reflected in it. However, If the caching is needed, it can be always done manually and explicitly</li> <li>It is better to reserve the <code class="docutils literal notranslate"><span class="pre">__signature__</span></code> attribute for the cases when there is a need to explicitly set to a <code class="docutils literal notranslate"><span class="pre">Signature</span></code> object that is different from the actual one</li> </ul> </section> <section id="some-functions-may-not-be-introspectable"> <h3><a class="toc-backref" href="#some-functions-may-not-be-introspectable" role="doc-backlink">Some functions may not be introspectable</a></h3> <p>Some functions may not be introspectable in certain implementations of Python. For example, in CPython, built-in functions defined in C provide no metadata about their arguments. Adding support for them is out of scope for this PEP.</p> </section> <section id="signature-and-parameter-equivalence"> <h3><a class="toc-backref" href="#signature-and-parameter-equivalence" role="doc-backlink">Signature and Parameter equivalence</a></h3> <p>We assume that parameter names have semantic significance–two signatures are equal only when their corresponding parameters are equal and have the exact same names. Users who want looser equivalence tests, perhaps ignoring names of VAR_KEYWORD or VAR_POSITIONAL parameters, will need to implement those themselves.</p> </section> </section> <section id="examples"> <h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2> <section id="visualizing-callable-objects-signature"> <h3><a class="toc-backref" href="#visualizing-callable-objects-signature" role="doc-backlink">Visualizing Callable Objects’ Signature</a></h3> <p>Let’s define some classes and functions:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="n">signature</span> <span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">partial</span><span class="p">,</span> <span class="n">wraps</span> <span class="k">class</span> <span class="nc">FooMeta</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span> <span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="n">mcls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">dct</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">bar</span><span class="p">:</span><span class="nb">bool</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span> <span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="n">mcls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">dct</span><span class="p">)</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">dct</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">dct</span><span class="p">)</span> <span class="k">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">FooMeta</span><span class="p">):</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">spam</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">42</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">spam</span> <span class="o">=</span> <span class="n">spam</span> <span class="k">def</span> <span class="fm">__call__</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="o">*</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span> <span class="o">-></span> <span class="nb">tuple</span><span class="p">:</span> <span class="k">return</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="nd">@classmethod</span> <span class="k">def</span> <span class="nf">spam</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span> <span class="k">return</span> <span class="n">a</span> <span class="k">def</span> <span class="nf">shared_vars</span><span class="p">(</span><span class="o">*</span><span class="n">shared_args</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Decorator factory that defines shared variables that are</span> <span class="sd"> passed to every invocation of the function"""</span> <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span> <span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</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">kwargs</span><span class="p">):</span> <span class="n">full_args</span> <span class="o">=</span> <span class="n">shared_args</span> <span class="o">+</span> <span class="n">args</span> <span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">full_args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="c1"># Override signature</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">signature</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">sig</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">())[</span><span class="mi">1</span><span class="p">:])</span> <span class="n">wrapper</span><span class="o">.</span><span class="n">__signature__</span> <span class="o">=</span> <span class="n">sig</span> <span class="k">return</span> <span class="n">wrapper</span> <span class="k">return</span> <span class="n">decorator</span> <span class="nd">@shared_vars</span><span class="p">({})</span> <span class="k">def</span> <span class="nf">example</span><span class="p">(</span><span class="n">_state</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="n">c</span><span class="p">):</span> <span class="k">return</span> <span class="n">_state</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="n">c</span> <span class="k">def</span> <span class="nf">format_signature</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span> <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">signature</span><span class="p">(</span><span class="n">obj</span><span class="p">))</span> </pre></div> </div> <p>Now, in the python REPL:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">FooMeta</span><span class="p">)</span> <span class="go">'(name, bases, dct, *, bar:bool=False)'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">Foo</span><span class="p">)</span> <span class="go">'(spam:int=42)'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">Foo</span><span class="o">.</span><span class="fm">__call__</span><span class="p">)</span> <span class="go">'(self, a, b, *, c) -> tuple'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">Foo</span><span class="p">()</span><span class="o">.</span><span class="fm">__call__</span><span class="p">)</span> <span class="go">'(a, b, *, c) -> tuple'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">Foo</span><span class="o">.</span><span class="n">spam</span><span class="p">)</span> <span class="go">'(a)'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">Foo</span><span class="p">()</span><span class="o">.</span><span class="fm">__call__</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">))</span> <span class="go">'(b, *, c=3) -> tuple'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">Foo</span><span class="p">()</span><span class="o">.</span><span class="fm">__call__</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">),</span> <span class="mi">2</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">20</span><span class="p">))</span> <span class="go">'(*, c=20) -> tuple'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">example</span><span class="p">)</span> <span class="go">'(a, b, c)'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">example</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="go">'(c)'</span> <span class="gp">>>> </span><span class="n">format_signature</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">partial</span><span class="p">(</span><span class="n">example</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="mi">2</span><span class="p">),</span> <span class="n">c</span><span class="o">=</span><span class="mi">3</span><span class="p">))</span> <span class="go">'(b=2, c=3)'</span> </pre></div> </div> </section> <section id="annotation-checker"> <h3><a class="toc-backref" href="#annotation-checker" role="doc-backlink">Annotation Checker</a></h3> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="nn">functools</span> <span class="k">def</span> <span class="nf">checktypes</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="w"> </span><span class="sd">'''Decorator to verify arguments and return types</span> <span class="sd"> Example:</span> <span class="sd"> >>> @checktypes</span> <span class="sd"> ... def test(a:int, b:str) -> int:</span> <span class="sd"> ... return int(a * b)</span> <span class="sd"> >>> test(10, '1')</span> <span class="sd"> 1111111111</span> <span class="sd"> >>> test(10, 1)</span> <span class="sd"> Traceback (most recent call last):</span> <span class="sd"> ...</span> <span class="sd"> ValueError: foo: wrong type of 'b' argument, 'str' expected, got 'int'</span> <span class="sd"> '''</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="n">types</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">sig</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="c1"># Iterate through function's parameters and build the list of</span> <span class="c1"># arguments types</span> <span class="n">type_</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="n">annotation</span> <span class="k">if</span> <span class="n">type_</span> <span class="ow">is</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isclass</span><span class="p">(</span><span class="n">type_</span><span class="p">):</span> <span class="c1"># Missing annotation or not a type, skip it</span> <span class="k">continue</span> <span class="n">types</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">type_</span> <span class="c1"># If the argument has a type specified, let's check that its</span> <span class="c1"># default value (if present) conforms with the type.</span> <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">default</span><span class="p">,</span> <span class="n">type_</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"</span><span class="si">{func}</span><span class="s2">: wrong type of a default value for </span><span class="si">{arg!r}</span><span class="s2">"</span><span class="o">.</span> \ <span class="nb">format</span><span class="p">(</span><span class="n">func</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="vm">__qualname__</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">))</span> <span class="k">def</span> <span class="nf">check_type</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="n">arg_name</span><span class="p">,</span> <span class="n">arg_type</span><span class="p">,</span> <span class="n">arg_value</span><span class="p">):</span> <span class="c1"># Internal function that encapsulates arguments type checking</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arg_value</span><span class="p">,</span> <span class="n">arg_type</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"</span><span class="si">{func}</span><span class="s2">: wrong type of </span><span class="si">{arg!r}</span><span class="s2"> argument, "</span> \ <span class="s2">"</span><span class="si">{exp!r}</span><span class="s2"> expected, got </span><span class="si">{got!r}</span><span class="s2">"</span><span class="o">.</span> \ <span class="nb">format</span><span class="p">(</span><span class="n">func</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="vm">__qualname__</span><span class="p">,</span> <span class="n">arg</span><span class="o">=</span><span class="n">arg_name</span><span class="p">,</span> <span class="n">exp</span><span class="o">=</span><span class="n">arg_type</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">got</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="n">arg_value</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">))</span> <span class="nd">@functools</span><span class="o">.</span><span class="n">wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</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">kwargs</span><span class="p">):</span> <span class="c1"># Let's bind the arguments</span> <span class="n">ba</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">bind</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">kwargs</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg_name</span><span class="p">,</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">ba</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="c1"># And iterate through the bound arguments</span> <span class="k">try</span><span class="p">:</span> <span class="n">type_</span> <span class="o">=</span> <span class="n">types</span><span class="p">[</span><span class="n">arg_name</span><span class="p">]</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="k">continue</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># OK, we have a type for the argument, lets get the corresponding</span> <span class="c1"># parameter description from the signature object</span> <span class="n">param</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">parameters</span><span class="p">[</span><span class="n">arg_name</span><span class="p">]</span> <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">:</span> <span class="c1"># If this parameter is a variable-argument parameter,</span> <span class="c1"># then we need to check each of its values</span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">:</span> <span class="n">check_type</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="n">arg_name</span><span class="p">,</span> <span class="n">type_</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">:</span> <span class="c1"># If this parameter is a variable-keyword-argument parameter:</span> <span class="k">for</span> <span class="n">subname</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">arg</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">check_type</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="n">arg_name</span> <span class="o">+</span> <span class="s1">':'</span> <span class="o">+</span> <span class="n">subname</span><span class="p">,</span> <span class="n">type_</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># And, finally, if this parameter a regular one:</span> <span class="n">check_type</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="n">arg_name</span><span class="p">,</span> <span class="n">type_</span><span class="p">,</span> <span class="n">arg</span><span class="p">)</span> <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">ba</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">ba</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span> <span class="c1"># The last bit - let's check that the result is correct</span> <span class="n">return_type</span> <span class="o">=</span> <span class="n">sig</span><span class="o">.</span><span class="n">return_annotation</span> <span class="k">if</span> <span class="p">(</span><span class="n">return_type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">sig</span><span class="o">.</span><span class="n">_empty</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">return_type</span><span class="p">,</span> <span class="nb">type</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">return_type</span><span class="p">)):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">'</span><span class="si">{func}</span><span class="s1">: wrong return type, </span><span class="si">{exp}</span><span class="s1"> expected, got </span><span class="si">{got}</span><span class="s1">'</span><span class="o">.</span> \ <span class="nb">format</span><span class="p">(</span><span class="n">func</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="vm">__qualname__</span><span class="p">,</span> <span class="n">exp</span><span class="o">=</span><span class="n">return_type</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">got</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">))</span> <span class="k">return</span> <span class="n">result</span> <span class="k">return</span> <span class="n">wrapper</span> </pre></div> </div> </section> </section> <section id="acceptance"> <h2><a class="toc-backref" href="#acceptance" role="doc-backlink">Acceptance</a></h2> <p><a class="pep reference internal" href="../pep-0362/" title="PEP 362 – Function Signature Object">PEP 362</a> was accepted by Guido, Friday, June 22, 2012 <a class="footnote-reference brackets" href="#accepted" id="id3">[3]</a> . The reference implementation was committed to trunk later that day.</p> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="impl" role="doc-footnote"> <dt class="label" id="impl">[<a href="#id1">1</a>]</dt> <dd>pep362 branch (<a class="reference external" href="https://bitbucket.org/1st1/cpython/overview">https://bitbucket.org/1st1/cpython/overview</a>)</aside> <aside class="footnote brackets" id="issue" role="doc-footnote"> <dt class="label" id="issue">[<a href="#id2">2</a>]</dt> <dd>issue 15008 (<a class="reference external" href="http://bugs.python.org/issue15008">http://bugs.python.org/issue15008</a>)</aside> <aside class="footnote brackets" id="accepted" role="doc-footnote"> <dt class="label" id="accepted">[<a href="#id3">3</a>]</dt> <dd>“A Desperate Plea For Introspection (aka: BDFAP Needed)” (<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2012-June/120682.html">https://mail.python.org/pipermail/python-dev/2012-June/120682.html</a>)</aside> </aside> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0362.rst">https://github.com/python/peps/blob/main/peps/pep-0362.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0362.rst">2023-09-09 17:39:29 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#signature-object">Signature Object</a></li> <li><a class="reference internal" href="#parameter-object">Parameter Object</a></li> <li><a class="reference internal" href="#boundarguments-object">BoundArguments Object</a></li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#design-considerations">Design Considerations</a><ul> <li><a class="reference internal" href="#no-implicit-caching-of-signature-objects">No implicit caching of Signature objects</a></li> <li><a class="reference internal" href="#some-functions-may-not-be-introspectable">Some functions may not be introspectable</a></li> <li><a class="reference internal" href="#signature-and-parameter-equivalence">Signature and Parameter equivalence</a></li> </ul> </li> <li><a class="reference internal" href="#examples">Examples</a><ul> <li><a class="reference internal" href="#visualizing-callable-objects-signature">Visualizing Callable Objects’ Signature</a></li> <li><a class="reference internal" href="#annotation-checker">Annotation Checker</a></li> </ul> </li> <li><a class="reference internal" href="#acceptance">Acceptance</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0362.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>