python-peps/pep-0575/index.html

1213 lines
127 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html 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 575 Unifying function/method classes | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0575/">
<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 575 Unifying function/method classes | peps.python.org'>
<meta property="og:description" content="Reorganize the class hierarchy for functions and methods with the goal of reducing the difference between built-in functions (implemented in C) and Python functions. Mainly, make built-in functions behave more like Python functions without sacrificing p...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0575/">
<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="Reorganize the class hierarchy for functions and methods with the goal of reducing the difference between built-in functions (implemented in C) and Python functions. Mainly, make built-in functions behave more like Python functions without sacrificing p...">
<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> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 575</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 575 Unifying function/method classes</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeroen Demeyer &lt;J.Demeyer&#32;&#97;t&#32;UGent.be&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</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">27-Mar-2018</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.8</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">31-Mar-2018, 12-Apr-2018, 27-Apr-2018, 05-May-2018</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#withdrawal-notice">Withdrawal notice</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#new-classes">New classes</a><ul>
<li><a class="reference internal" href="#base-function">base_function</a></li>
<li><a class="reference internal" href="#cfunction">cfunction</a></li>
<li><a class="reference internal" href="#defined-function">defined_function</a></li>
<li><a class="reference internal" href="#function">function</a></li>
<li><a class="reference internal" href="#bound-method">bound_method</a></li>
</ul>
</li>
<li><a class="reference internal" href="#calling-base-function-instances">Calling base_function instances</a><ul>
<li><a class="reference internal" href="#checking-objclass">Checking __objclass__</a></li>
<li><a class="reference internal" href="#flags">Flags</a></li>
<li><a class="reference internal" href="#self-slicing">Self slicing</a></li>
<li><a class="reference internal" href="#meth-pass-function">METH_PASS_FUNCTION</a></li>
<li><a class="reference internal" href="#meth-fastcall">METH_FASTCALL</a></li>
</ul>
</li>
<li><a class="reference internal" href="#automatic-creation-of-built-in-functions">Automatic creation of built-in functions</a><ul>
<li><a class="reference internal" href="#unbound-methods-of-extension-types">Unbound methods of extension types</a></li>
<li><a class="reference internal" href="#built-in-functions-of-a-module">Built-in functions of a module</a></li>
</ul>
</li>
<li><a class="reference internal" href="#further-changes">Further changes</a><ul>
<li><a class="reference internal" href="#new-type-flag">New type flag</a></li>
<li><a class="reference internal" href="#c-api-functions">C API functions</a></li>
<li><a class="reference internal" href="#changes-to-the-types-module">Changes to the types module</a></li>
<li><a class="reference internal" href="#changes-to-the-inspect-module">Changes to the inspect module</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
</ul>
</li>
<li><a class="reference internal" href="#non-cpython-implementations">Non-CPython implementations</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#why-not-simply-change-existing-classes">Why not simply change existing classes?</a></li>
<li><a class="reference internal" href="#why-text-signature-is-not-a-solution">Why __text_signature__ is not a solution</a></li>
<li><a class="reference internal" href="#defined-function-versus-function">defined_function versus function</a></li>
<li><a class="reference internal" href="#scope-of-this-pep-which-classes-are-involved">Scope of this PEP: which classes are involved?</a></li>
<li><a class="reference internal" href="#not-treating-meth-static-and-meth-class">Not treating METH_STATIC and METH_CLASS</a></li>
<li><a class="reference internal" href="#self-in-base-function">__self__ in base_function</a></li>
<li><a class="reference internal" href="#two-implementations-of-doc">Two implementations of __doc__</a></li>
<li><a class="reference internal" href="#subclassing">Subclassing</a></li>
<li><a class="reference internal" href="#replacing-tp-call-meth-pass-function-and-meth-call-unbound">Replacing tp_call: METH_PASS_FUNCTION and METH_CALL_UNBOUND</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a><ul>
<li><a class="reference internal" href="#changes-to-types-and-inspect">Changes to types and inspect</a></li>
<li><a class="reference internal" href="#python-functions">Python functions</a></li>
<li><a class="reference internal" href="#id7">Built-in functions of a module</a></li>
<li><a class="reference internal" href="#built-in-bound-and-unbound-methods">Built-in bound and unbound methods</a></li>
<li><a class="reference internal" href="#new-attributes">New attributes</a></li>
<li><a class="reference internal" href="#method-descriptor-and-pydescr-newmethod">method_descriptor and PyDescr_NewMethod</a></li>
</ul>
</li>
<li><a class="reference internal" href="#two-phase-implementation">Two-phase Implementation</a><ul>
<li><a class="reference internal" href="#phase-one-keep-existing-classes-but-add-base-classes">Phase one: keep existing classes but add base classes</a></li>
<li><a class="reference internal" href="#phase-two">Phase two</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#appendix-current-situation">Appendix: current situation</a><ul>
<li><a class="reference internal" href="#builtin-function-or-method-built-in-functions-and-bound-methods">builtin_function_or_method: built-in functions and bound methods</a></li>
<li><a class="reference internal" href="#method-descriptor-built-in-unbound-methods">method_descriptor: built-in unbound methods</a></li>
<li><a class="reference internal" href="#function-python-functions">function: Python functions</a></li>
<li><a class="reference internal" href="#method-python-bound-methods">method: Python bound methods</a></li>
</ul>
</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="withdrawal-notice">
<h2><a class="toc-backref" href="#withdrawal-notice" role="doc-backlink">Withdrawal notice</a></h2>
<p>See <a class="pep reference internal" href="../pep-0580/" title="PEP 580 The C call protocol">PEP 580</a> for a better solution to allowing fast calling of custom classes.</p>
<p>See <a class="pep reference internal" href="../pep-0579/" title="PEP 579 Refactoring C functions and methods">PEP 579</a> for a broader discussion of some of the other issues from this PEP.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Reorganize the class hierarchy for functions and methods
with the goal of reducing the difference between
built-in functions (implemented in C) and Python functions.
Mainly, make built-in functions behave more like Python functions
without sacrificing performance.</p>
<p>A new base class <code class="docutils literal notranslate"><span class="pre">base_function</span></code> is introduced and the various function
classes, as well as <code class="docutils literal notranslate"><span class="pre">method</span></code> (renamed to <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>), inherit from it.</p>
<p>We also allow subclassing the Python <code class="docutils literal notranslate"><span class="pre">function</span></code> class.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Currently, CPython has two different function classes:
the first is Python functions, which is what you get
when defining a function with <code class="docutils literal notranslate"><span class="pre">def</span></code> or <code class="docutils literal notranslate"><span class="pre">lambda</span></code>.
The second is built-in functions such as <code class="docutils literal notranslate"><span class="pre">len</span></code>, <code class="docutils literal notranslate"><span class="pre">isinstance</span></code> or <code class="docutils literal notranslate"><span class="pre">numpy.dot</span></code>.
These are implemented in C.</p>
<p>These two classes are implemented completely independently and have different functionality.
In particular, it is currently not possible to implement a function efficiently in C
(only built-in functions can do that)
while still allowing introspection like <code class="docutils literal notranslate"><span class="pre">inspect.signature</span></code> or <code class="docutils literal notranslate"><span class="pre">inspect.getsourcefile</span></code>
(only Python functions can do that).
This is a problem for projects like Cython <a class="footnote-reference brackets" href="#cython" id="id1">[1]</a> that want to do exactly that.</p>
<p>In Cython, this was worked around by inventing a new function class called <code class="docutils literal notranslate"><span class="pre">cyfunction</span></code>.
Unfortunately, a new function class creates problems:
the <code class="docutils literal notranslate"><span class="pre">inspect</span></code> module does not recognize such functions as being functions <a class="footnote-reference brackets" href="#bpo30071" id="id2">[2]</a>
and the performance is worse
(CPython has specific optimizations for calling built-in functions).</p>
<p>A second motivation is more generally making built-in functions and methods
behave more like Python functions and methods.
For example, Python unbound methods are just functions but
unbound methods of extension types (e.g. <code class="docutils literal notranslate"><span class="pre">dict.get</span></code>) are a distinct class.
Bound methods of Python classes have a <code class="docutils literal notranslate"><span class="pre">__func__</span></code> attribute,
bound methods of extension types do not.</p>
<p>Third, this PEP allows great customization of functions.
The <code class="docutils literal notranslate"><span class="pre">function</span></code> class becomes subclassable and custom function
subclasses are also allowed for functions implemented in C.
In the latter case, this can be done with the same performance
as true built-in functions.
All functions can access the function object
(the <code class="docutils literal notranslate"><span class="pre">self</span></code> in <code class="docutils literal notranslate"><span class="pre">__call__</span></code>), paving the way for <a class="pep reference internal" href="../pep-0573/" title="PEP 573 Module State Access from C Extension Methods">PEP 573</a>.</p>
</section>
<section id="new-classes">
<h2><a class="toc-backref" href="#new-classes" role="doc-backlink">New classes</a></h2>
<p>This is the new class hierarchy for functions and methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nb">object</span>
<span class="o">|</span>
<span class="o">|</span>
<span class="n">base_function</span>
<span class="o">/</span> <span class="o">|</span> \
<span class="o">/</span> <span class="o">|</span> \
<span class="o">/</span> <span class="o">|</span> <span class="n">defined_function</span>
<span class="o">/</span> <span class="o">|</span> \
<span class="n">cfunction</span> <span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="o">|</span> \
<span class="o">|</span> <span class="n">function</span>
<span class="o">|</span>
<span class="n">bound_method</span> <span class="p">(</span><span class="o">*</span><span class="p">)</span>
</pre></div>
</div>
<p>The two classes marked with (*) do <em>not</em> allow subclassing;
the others do.</p>
<p>There is no difference between functions and unbound methods,
while bound methods are instances of <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>.</p>
<section id="base-function">
<h3><a class="toc-backref" href="#base-function" role="doc-backlink">base_function</a></h3>
<p>The class <code class="docutils literal notranslate"><span class="pre">base_function</span></code> becomes a new base class for all function types.
It is based on the existing <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> class,
but with the following differences and new features:</p>
<ol class="arabic simple">
<li>It acts as a descriptor implementing <code class="docutils literal notranslate"><span class="pre">__get__</span></code> to turn a function into a method
if <code class="docutils literal notranslate"><span class="pre">m_self</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.
If <code class="docutils literal notranslate"><span class="pre">m_self</span></code> is not <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,
then this is a no-op: the existing function is returned instead.</li>
<li>A new read-only attribute <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>, represented in the C structure as <code class="docutils literal notranslate"><span class="pre">m_parent</span></code>.
If this attribute exists, it represents the defining object.
For methods of extension types, this is the defining class (<code class="docutils literal notranslate"><span class="pre">__class__</span></code> in plain Python)
and for functions of a module, this is the defining module.
In general, it can be any Python object.
If <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> is a class, it carries special semantics:
in that case, the function must be called with <code class="docutils literal notranslate"><span class="pre">self</span></code> being an instance of that class.
Finally, <code class="docutils literal notranslate"><span class="pre">__qualname__</span></code> and <code class="docutils literal notranslate"><span class="pre">__reduce__</span></code> will use <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>
as namespace (instead of <code class="docutils literal notranslate"><span class="pre">__self__</span></code> before).</li>
<li>A new attribute <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> which equals <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> if <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>
is a class. Otherwise, accessing <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> raises <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code>.
This is meant to be backwards compatible with <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.</li>
<li>The field <code class="docutils literal notranslate"><span class="pre">ml_doc</span></code> and the attributes <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code> (see <a class="pep reference internal" href="../pep-0436/" title="PEP 436 The Argument Clinic DSL">Argument Clinic</a>)
are not supported.</li>
<li>A new flag <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> for <code class="docutils literal notranslate"><span class="pre">ml_flags</span></code>.
If this flag is set, the C function stored in <code class="docutils literal notranslate"><span class="pre">ml_meth</span></code> is called with
an additional first argument equal to the function object.</li>
<li>A new flag <code class="docutils literal notranslate"><span class="pre">METH_BINDING</span></code> for <code class="docutils literal notranslate"><span class="pre">ml_flags</span></code> which only applies to
functions of a module (not methods of a class).
If this flag is set, then <code class="docutils literal notranslate"><span class="pre">m_self</span></code> is set to <code class="docutils literal notranslate"><span class="pre">NULL</span></code> instead
of the module.
This allows the function to behave more like a Python function
as it enables <code class="docutils literal notranslate"><span class="pre">__get__</span></code>.</li>
<li>A new flag <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code> to disable <a class="reference internal" href="#self-slicing">self slicing</a>.</li>
<li>A new flag <code class="docutils literal notranslate"><span class="pre">METH_PYTHON</span></code> for <code class="docutils literal notranslate"><span class="pre">ml_flags</span></code>.
This flag indicates that this function should be treated as Python function.
Ideally, use of this flag should be avoided because it goes
against the duck typing philosophy.
It is still needed in a few places though, for example <a class="reference internal" href="#profiling">profiling</a>.</li>
</ol>
<p>The goal of <code class="docutils literal notranslate"><span class="pre">base_function</span></code> is that it supports all different ways
of calling functions and methods in just one structure.
For example, the new flag <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code>
will be used by the implementation of methods.</p>
<p>It is not possible to directly create instances of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>
(<code class="docutils literal notranslate"><span class="pre">tp_new</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>).
However, it is legal for C code to manually create instances.</p>
<p>These are the relevant C structures:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyTypeObject</span> <span class="n">PyBaseFunction_Type</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyCFunctionDef</span> <span class="o">*</span><span class="n">m_ml</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Description</span> <span class="n">of</span> <span class="n">the</span> <span class="n">C</span> <span class="n">function</span> <span class="n">to</span> <span class="n">call</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_self</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__self__</span><span class="p">:</span> <span class="n">anything</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">readonly</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_module</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__module__</span><span class="p">:</span> <span class="n">anything</span> <span class="p">(</span><span class="n">typically</span> <span class="nb">str</span><span class="p">)</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_parent</span><span class="p">;</span> <span class="o">/*</span> <span class="n">__parent__</span><span class="p">:</span> <span class="n">anything</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">readonly</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_weakreflist</span><span class="p">;</span> <span class="o">/*</span> <span class="n">List</span> <span class="n">of</span> <span class="n">weak</span> <span class="n">references</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyBaseFunctionObject</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">ml_name</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">name</span> <span class="n">of</span> <span class="n">the</span> <span class="n">built</span><span class="o">-</span><span class="ow">in</span> <span class="n">function</span><span class="o">/</span><span class="n">method</span> <span class="o">*/</span>
<span class="n">PyCFunction</span> <span class="n">ml_meth</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">C</span> <span class="n">function</span> <span class="n">that</span> <span class="n">implements</span> <span class="n">it</span> <span class="o">*/</span>
<span class="nb">int</span> <span class="n">ml_flags</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Combination</span> <span class="n">of</span> <span class="n">METH_xxx</span> <span class="n">flags</span><span class="p">,</span> <span class="n">which</span> <span class="n">mostly</span>
<span class="n">describe</span> <span class="n">the</span> <span class="n">args</span> <span class="n">expected</span> <span class="n">by</span> <span class="n">the</span> <span class="n">C</span> <span class="n">func</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyCFunctionDef</span><span class="p">;</span>
</pre></div>
</div>
<p>Subclasses may extend <code class="docutils literal notranslate"><span class="pre">PyCFunctionDef</span></code> with extra fields.</p>
<p>The Python attribute <code class="docutils literal notranslate"><span class="pre">__self__</span></code> returns <code class="docutils literal notranslate"><span class="pre">m_self</span></code>,
except if <code class="docutils literal notranslate"><span class="pre">METH_STATIC</span></code> is set.
In that case or if <code class="docutils literal notranslate"><span class="pre">m_self</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,
then there is no <code class="docutils literal notranslate"><span class="pre">__self__</span></code> attribute at all.
For that reason, we write either <code class="docutils literal notranslate"><span class="pre">m_self</span></code> or <code class="docutils literal notranslate"><span class="pre">__self__</span></code> in this PEP
with slightly different meanings.</p>
</section>
<section id="cfunction">
<h3><a class="toc-backref" href="#cfunction" role="doc-backlink">cfunction</a></h3>
<p>This is the new version of the old <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> class.
The name <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> was chosen to avoid confusion with “built-in”
in the sense of “something in the <code class="docutils literal notranslate"><span class="pre">builtins</span></code> module”.
It also fits better with the C API which use the <code class="docutils literal notranslate"><span class="pre">PyCFunction</span></code> prefix.</p>
<p>The class <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> is a copy of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>, with the following differences:</p>
<ol class="arabic">
<li><code class="docutils literal notranslate"><span class="pre">m_ml</span></code> points to a <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure,
extending <code class="docutils literal notranslate"><span class="pre">PyCFunctionDef</span></code> with an additional <code class="docutils literal notranslate"><span class="pre">ml_doc</span></code>
field to implement <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> and <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code>
as read-only attributes:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">ml_name</span><span class="p">;</span>
<span class="n">PyCFunction</span> <span class="n">ml_meth</span><span class="p">;</span>
<span class="nb">int</span> <span class="n">ml_flags</span><span class="p">;</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">ml_doc</span><span class="p">;</span>
<span class="p">}</span> <span class="n">PyMethodDef</span><span class="p">;</span>
</pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> is part of the <a class="pep reference internal" href="../pep-0384/" title="PEP 384 Defining a Stable ABI">Python Stable ABI</a>
and it is used by practically all extension modules,
so we absolutely cannot change this structure.</p>
</li>
<li><a class="pep reference internal" href="../pep-0436/" title="PEP 436 The Argument Clinic DSL">Argument Clinic</a> is supported.</li>
<li><code class="docutils literal notranslate"><span class="pre">__self__</span></code> always exists. In the cases where <code class="docutils literal notranslate"><span class="pre">base_function.__self__</span></code>
would raise <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code>, instead <code class="docutils literal notranslate"><span class="pre">None</span></code> is returned.</li>
</ol>
<p>The type object is <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span> <span class="pre">PyCFunction_Type</span></code>
and we define <code class="docutils literal notranslate"><span class="pre">PyCFunctionObject</span></code> as alias of <code class="docutils literal notranslate"><span class="pre">PyBaseFunctionObject</span></code>
(except for the type of <code class="docutils literal notranslate"><span class="pre">m_ml</span></code>).</p>
</section>
<section id="defined-function">
<h3><a class="toc-backref" href="#defined-function" role="doc-backlink">defined_function</a></h3>
<p>The class <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> is an abstract base class meant
to indicate that the function has introspection support.
Instances of <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> are required to support all attributes
that Python functions have, namely
<code class="docutils literal notranslate"><span class="pre">__code__</span></code>, <code class="docutils literal notranslate"><span class="pre">__globals__</span></code>, <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__defaults__</span></code>, <code class="docutils literal notranslate"><span class="pre">__kwdefaults__</span></code>, <code class="docutils literal notranslate"><span class="pre">__closure__</span></code> and <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.
There is also a <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> to support attributes added by the user.</p>
<p>None of these is required to be meaningful.
In particular, <code class="docutils literal notranslate"><span class="pre">__code__</span></code> may not be a working code object,
possibly only a few fields may be filled in.
This PEP does not dictate how the various attributes are implemented.
They may be simple struct members or more complicated descriptors.
Only read-only support is required, none of the attributes is required to be writable.</p>
<p>The class <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> is mainly meant for auto-generated C code,
for example produced by Cython <a class="footnote-reference brackets" href="#cython" id="id3">[1]</a>.
There is no API to create instances of it.</p>
<p>The C structure is the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyTypeObject</span> <span class="n">PyDefinedFunction_Type</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyBaseFunctionObject</span> <span class="n">base</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_dict</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__dict__</span><span class="p">:</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyDefinedFunctionObject</span><span class="p">;</span>
</pre></div>
</div>
<p><strong>TODO</strong>: maybe find a better name for <code class="docutils literal notranslate"><span class="pre">defined_function</span></code>.
Other proposals: <code class="docutils literal notranslate"><span class="pre">inspect_function</span></code> (anything that satisfies <code class="docutils literal notranslate"><span class="pre">inspect.isfunction</span></code>),
<code class="docutils literal notranslate"><span class="pre">builtout_function</span></code> (a function that is better built out; pun on builtin),
<code class="docutils literal notranslate"><span class="pre">generic_function</span></code> (original proposal but conflicts with <code class="docutils literal notranslate"><span class="pre">functools.singledispatch</span></code> generic functions),
<code class="docutils literal notranslate"><span class="pre">user_function</span></code> (defined by the user as opposed to CPython).</p>
</section>
<section id="function">
<h3><a class="toc-backref" href="#function" role="doc-backlink">function</a></h3>
<p>This is the class meant for functions implemented in Python.
Unlike the other function types,
instances of <code class="docutils literal notranslate"><span class="pre">function</span></code> can be created from Python code.
This is not changed, so we do not describe the details in this PEP.</p>
<p>The layout of the C structure is the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyTypeObject</span> <span class="n">PyFunction_Type</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyBaseFunctionObject</span> <span class="n">base</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_dict</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__dict__</span><span class="p">:</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_code</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__code__</span><span class="p">:</span> <span class="n">code</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_globals</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__globals__</span><span class="p">:</span> <span class="nb">dict</span><span class="p">;</span> <span class="n">readonly</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_name</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__name__</span><span class="p">:</span> <span class="n">string</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_qualname</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__qualname__</span><span class="p">:</span> <span class="n">string</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_doc</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__doc__</span><span class="p">:</span> <span class="n">can</span> <span class="n">be</span> <span class="n">anything</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_defaults</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__defaults__</span><span class="p">:</span> <span class="nb">tuple</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_kwdefaults</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__kwdefaults__</span><span class="p">:</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_closure</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__closure__</span><span class="p">:</span> <span class="nb">tuple</span> <span class="n">of</span> <span class="n">cell</span> <span class="n">objects</span> <span class="ow">or</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">readonly</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_annotations</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__annotations__</span><span class="p">:</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyCFunctionDef</span> <span class="n">_ml</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Storage</span> <span class="k">for</span> <span class="n">base</span><span class="o">.</span><span class="n">m_ml</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyFunctionObject</span><span class="p">;</span>
</pre></div>
</div>
<p>The descriptor <code class="docutils literal notranslate"><span class="pre">__name__</span></code> returns <code class="docutils literal notranslate"><span class="pre">func_name</span></code>.
When setting <code class="docutils literal notranslate"><span class="pre">__name__</span></code>, also <code class="docutils literal notranslate"><span class="pre">base.m_ml-&gt;ml_name</span></code> is updated
with the UTF-8 encoded name.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">_ml</span></code> field reserves space to be used by <code class="docutils literal notranslate"><span class="pre">base.m_ml</span></code>.</p>
<p>A <code class="docutils literal notranslate"><span class="pre">base_function</span></code> instance must have the flag <code class="docutils literal notranslate"><span class="pre">METH_PYTHON</span></code> set
if and only if it is an instance of <code class="docutils literal notranslate"><span class="pre">function</span></code>.</p>
<p>When constructing an instance of <code class="docutils literal notranslate"><span class="pre">function</span></code> from <code class="docutils literal notranslate"><span class="pre">code</span></code> and <code class="docutils literal notranslate"><span class="pre">globals</span></code>,
an instance is created with <code class="docutils literal notranslate"><span class="pre">base.m_ml</span> <span class="pre">=</span> <span class="pre">&amp;_ml</span></code>,
<code class="docutils literal notranslate"><span class="pre">base.m_self</span> <span class="pre">=</span> <span class="pre">NULL</span></code>.</p>
<p>To make subclassing easier, we also add a copy constructor:
if <code class="docutils literal notranslate"><span class="pre">f</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">function</span></code>, then <code class="docutils literal notranslate"><span class="pre">types.FunctionType(f)</span></code> copies <code class="docutils literal notranslate"><span class="pre">f</span></code>.
This conveniently allows using a custom function type as decorator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">types</span> <span class="kn">import</span> <span class="n">FunctionType</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">CustomFunction</span><span class="p">(</span><span class="n">FunctionType</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nd">@CustomFunction</span>
<span class="gp">... </span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">x</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">type</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="go">&lt;class &#39;__main__.CustomFunction&#39;&gt;</span>
</pre></div>
</div>
<p>This also removes many use cases of <code class="docutils literal notranslate"><span class="pre">functools.wraps</span></code>:
wrappers can be replaced by subclasses of <code class="docutils literal notranslate"><span class="pre">function</span></code>.</p>
</section>
<section id="bound-method">
<h3><a class="toc-backref" href="#bound-method" role="doc-backlink">bound_method</a></h3>
<p>The class <code class="docutils literal notranslate"><span class="pre">bound_method</span></code> is used for all bound methods,
regardless of the class of the underlying function.
It adds one new attribute on top of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>:
<code class="docutils literal notranslate"><span class="pre">__func__</span></code> points to that function.</p>
<p><code class="docutils literal notranslate"><span class="pre">bound_method</span></code> replaces the old <code class="docutils literal notranslate"><span class="pre">method</span></code> class
which was used only for Python functions bound as method.</p>
<p>There is a complication because we want to allow
constructing a method from an arbitrary callable.
This may be an already-bound method or simply not an instance of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.
Therefore, in practice there are two kinds of methods:</p>
<ul class="simple">
<li>For arbitrary callables, we use a single fixed <code class="docutils literal notranslate"><span class="pre">PyCFunctionDef</span></code>
structure with the <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> flag set.</li>
<li>For methods which bind instances of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>
(more precisely, which have the <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_BASEFUNCTION</span></code> flag set)
that have <a class="reference internal" href="#self-slicing">self slicing</a>,
we instead use the <code class="docutils literal notranslate"><span class="pre">PyCFunctionDef</span></code> from the original function.
This way, we dont lose any performance when calling bound methods.
In this case, the <code class="docutils literal notranslate"><span class="pre">__func__</span></code> attribute is only used to implement
various attributes but not for calling the method.</li>
</ul>
<p>When constructing a new method from a <code class="docutils literal notranslate"><span class="pre">base_function</span></code>,
we check that the <code class="docutils literal notranslate"><span class="pre">self</span></code> object is an instance of <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code>
(if a class was specified as parent) and raise a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> otherwise.</p>
<p>The C structure is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyTypeObject</span> <span class="n">PyMethod_Type</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyBaseFunctionObject</span> <span class="n">base</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">im_func</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__func__</span><span class="p">:</span> <span class="n">function</span> <span class="n">implementing</span> <span class="n">the</span> <span class="n">method</span><span class="p">;</span> <span class="n">readonly</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyMethodObject</span><span class="p">;</span>
</pre></div>
</div>
</section>
</section>
<section id="calling-base-function-instances">
<h2><a class="toc-backref" href="#calling-base-function-instances" role="doc-backlink">Calling base_function instances</a></h2>
<p>We specify the implementation of <code class="docutils literal notranslate"><span class="pre">__call__</span></code> for instances of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.</p>
<section id="checking-objclass">
<h3><a class="toc-backref" href="#checking-objclass" role="doc-backlink">Checking __objclass__</a></h3>
<p>First of all, a type check is done if the <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> of the function
is a class
(recall that <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> then becomes an alias of <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>):
if <code class="docutils literal notranslate"><span class="pre">m_self</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code> (this is the case for unbound methods of extension types),
then the function must be called with at least one positional argument
and the first (typically called <code class="docutils literal notranslate"><span class="pre">self</span></code>) must be an instance of <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code>.
If not, a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</p>
<p>Note that bound methods have <code class="docutils literal notranslate"><span class="pre">m_self</span> <span class="pre">!=</span> <span class="pre">NULL</span></code>, so the <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code>
is not checked.
Instead, the <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> check is done when constructing the method.</p>
</section>
<section id="flags">
<h3><a class="toc-backref" href="#flags" role="doc-backlink">Flags</a></h3>
<p>For convenience, we define a new constant:
<code class="docutils literal notranslate"><span class="pre">METH_CALLFLAGS</span></code> combines all flags from <code class="docutils literal notranslate"><span class="pre">PyCFunctionDef.ml_flags</span></code>
which specify the signature of the C function to be called.
It is equal to</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">METH_VARARGS</span> <span class="o">|</span> <span class="n">METH_FASTCALL</span> <span class="o">|</span> <span class="n">METH_NOARGS</span> <span class="o">|</span> <span class="n">METH_O</span> <span class="o">|</span> <span class="n">METH_KEYWORDS</span> <span class="o">|</span> <span class="n">METH_PASS_FUNCTION</span>
</pre></div>
</div>
<p>Exactly one of the first four flags above must be set
and only <code class="docutils literal notranslate"><span class="pre">METH_VARARGS</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span></code> may be combined with <code class="docutils literal notranslate"><span class="pre">METH_KEYWORDS</span></code>.
Violating these rules is undefined behaviour.</p>
<p>There are one new flags which affects calling functions,
namely <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code>.
Some flags are already documented in <a class="footnote-reference brackets" href="#methoddoc" id="id4">[5]</a>.
We explain the others below.</p>
</section>
<section id="self-slicing">
<h3><a class="toc-backref" href="#self-slicing" role="doc-backlink">Self slicing</a></h3>
<p>If the function has <code class="docutils literal notranslate"><span class="pre">m_self</span> <span class="pre">==</span> <span class="pre">NULL</span></code> and the flag <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code>
is not set, then the first positional argument (if any)
is removed from <code class="docutils literal notranslate"><span class="pre">*args</span></code> and instead passed as first argument to the C function.
Effectively, the first positional argument is treated as <code class="docutils literal notranslate"><span class="pre">__self__</span></code>.
This is meant to support unbound methods
such that the C function does not see the difference
between bound and unbound method calls.
This does not affect keyword arguments in any way.</p>
<p>This process is called <em>self slicing</em> and a function is said to
<em>have self slicing</em> if <code class="docutils literal notranslate"><span class="pre">m_self</span> <span class="pre">==</span> <span class="pre">NULL</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code> is not set.</p>
<p>Note that a <code class="docutils literal notranslate"><span class="pre">METH_NOARGS</span></code> function which has self slicing
effectively has one argument, namely <code class="docutils literal notranslate"><span class="pre">self</span></code>.
Analogously, a <code class="docutils literal notranslate"><span class="pre">METH_O</span></code> function with self slicing has two arguments.</p>
</section>
<section id="meth-pass-function">
<h3><a class="toc-backref" href="#meth-pass-function" role="doc-backlink">METH_PASS_FUNCTION</a></h3>
<p>If this flag is set, then the C function is called with an
additional first argument, namely the function itself
(the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> instance).
As special case, if the function is a <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>,
then the underlying function of the method is passed
(but not recursively: if a <code class="docutils literal notranslate"><span class="pre">bound_method</span></code> wraps a <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>,
then <code class="docutils literal notranslate"><span class="pre">__func__</span></code> is only applied once).</p>
<p>For example, an ordinary <code class="docutils literal notranslate"><span class="pre">METH_VARARGS</span></code> function has signature
<code class="docutils literal notranslate"><span class="pre">(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*args)</span></code>.
With <code class="docutils literal notranslate"><span class="pre">METH_VARARGS</span> <span class="pre">|</span> <span class="pre">METH_PASS_FUNCTION</span></code>, this becomes
<code class="docutils literal notranslate"><span class="pre">(PyObject</span> <span class="pre">*func,</span> <span class="pre">PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*args)</span></code>.</p>
</section>
<section id="meth-fastcall">
<h3><a class="toc-backref" href="#meth-fastcall" role="doc-backlink">METH_FASTCALL</a></h3>
<p>This is an existing but undocumented flag.
We suggest to officially support and document it.</p>
<p>If the flag <code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span></code> is set without <code class="docutils literal notranslate"><span class="pre">METH_KEYWORDS</span></code>,
then the <code class="docutils literal notranslate"><span class="pre">ml_meth</span></code> field is of type <code class="docutils literal notranslate"><span class="pre">PyCFunctionFast</span></code>
which takes the arguments <code class="docutils literal notranslate"><span class="pre">(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*const</span> <span class="pre">*args,</span> <span class="pre">Py_ssize_t</span> <span class="pre">nargs)</span></code>.
Such a function takes only positional arguments and they are passed as plain C array
<code class="docutils literal notranslate"><span class="pre">args</span></code> of length <code class="docutils literal notranslate"><span class="pre">nargs</span></code>.</p>
<p>If the flags <code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span> <span class="pre">|</span> <span class="pre">METH_KEYWORDS</span></code> are set,
then the <code class="docutils literal notranslate"><span class="pre">ml_meth</span></code> field is of type <code class="docutils literal notranslate"><span class="pre">PyCFunctionFastKeywords</span></code>
which takes the arguments <code class="docutils literal notranslate"><span class="pre">(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*const</span> <span class="pre">*args,</span> <span class="pre">Py_ssize_t</span> <span class="pre">nargs,</span> <span class="pre">PyObject</span> <span class="pre">*kwnames)</span></code>.
The positional arguments are passed as C array <code class="docutils literal notranslate"><span class="pre">args</span></code> of length <code class="docutils literal notranslate"><span class="pre">nargs</span></code>.
The <em>values</em> of the keyword arguments follow in that array,
starting at position <code class="docutils literal notranslate"><span class="pre">nargs</span></code>.
The <em>keys</em> (names) of the keyword arguments are passed as a <code class="docutils literal notranslate"><span class="pre">tuple</span></code> in <code class="docutils literal notranslate"><span class="pre">kwnames</span></code>.
As an example, assume that 3 positional and 2 keyword arguments are given.
Then <code class="docutils literal notranslate"><span class="pre">args</span></code> is an array of length 3 + 2 = 5, <code class="docutils literal notranslate"><span class="pre">nargs</span></code> equals 3 and <code class="docutils literal notranslate"><span class="pre">kwnames</span></code> is a 2-tuple.</p>
</section>
</section>
<section id="automatic-creation-of-built-in-functions">
<h2><a class="toc-backref" href="#automatic-creation-of-built-in-functions" role="doc-backlink">Automatic creation of built-in functions</a></h2>
<p>Python automatically generates instances of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>
for extension types (using the <code class="docutils literal notranslate"><span class="pre">PyTypeObject.tp_methods</span></code> field) and modules
(using the <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_methods</span></code> field).
The arrays <code class="docutils literal notranslate"><span class="pre">PyTypeObject.tp_methods</span></code> and <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_methods</span></code>
must be arrays of <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structures.</p>
<section id="unbound-methods-of-extension-types">
<h3><a class="toc-backref" href="#unbound-methods-of-extension-types" role="doc-backlink">Unbound methods of extension types</a></h3>
<p>The type of unbound methods changes from <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>
to <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.
The object which appears as unbound method is the same object which
appears in the class <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>.
Python automatically sets the <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> attribute to the defining class.</p>
</section>
<section id="built-in-functions-of-a-module">
<h3><a class="toc-backref" href="#built-in-functions-of-a-module" role="doc-backlink">Built-in functions of a module</a></h3>
<p>For the case of functions of a module,
<code class="docutils literal notranslate"><span class="pre">__parent__</span></code> will be set to the module.
Unless the flag <code class="docutils literal notranslate"><span class="pre">METH_BINDING</span></code> is given, also <code class="docutils literal notranslate"><span class="pre">__self__</span></code>
will be set to the module (for backwards compatibility).</p>
<p>An important consequence is that such functions by default
do not become methods when used as attribute
(<code class="docutils literal notranslate"><span class="pre">base_function.__get__</span></code> only does that if <code class="docutils literal notranslate"><span class="pre">m_self</span></code> was <code class="docutils literal notranslate"><span class="pre">NULL</span></code>).
One could consider this a bug, but this was done for backwards compatibility reasons:
in an initial post on python-ideas <a class="footnote-reference brackets" href="#proposal" id="id5">[6]</a> the consensus was to keep this
misfeature of built-in functions.</p>
<p>However, to allow this anyway for specific or newly implemented
built-in functions, the <code class="docutils literal notranslate"><span class="pre">METH_BINDING</span></code> flag prevents setting <code class="docutils literal notranslate"><span class="pre">__self__</span></code>.</p>
</section>
</section>
<section id="further-changes">
<h2><a class="toc-backref" href="#further-changes" role="doc-backlink">Further changes</a></h2>
<section id="new-type-flag">
<h3><a class="toc-backref" href="#new-type-flag" role="doc-backlink">New type flag</a></h3>
<p>A new <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> flag (for <code class="docutils literal notranslate"><span class="pre">tp_flags</span></code>) is added:
<code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_BASEFUNCTION</span></code> to indicate that instances of this type are
functions which can be called and bound as method like a <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.</p>
<p>This is different from flags like <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_LIST_SUBCLASS</span></code>
because it indicates more than just a subclass:
it also indicates a default implementation of <code class="docutils literal notranslate"><span class="pre">__call__</span></code> and <code class="docutils literal notranslate"><span class="pre">__get__</span></code>.
In particular, such subclasses of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>
must follow the implementation from the section <a class="reference internal" href="#calling-base-function-instances">Calling base_function instances</a>.</p>
<p>This flag is automatically set for extension types which
inherit the <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_descr_get</span></code> implementation from <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.
Extension types can explicitly specify it if they
override <code class="docutils literal notranslate"><span class="pre">__call__</span></code> or <code class="docutils literal notranslate"><span class="pre">__get__</span></code> in a compatible way.
The flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_BASEFUNCTION</span></code> must never be set for a heap type
because that would not be safe (heap types can be changed dynamically).</p>
</section>
<section id="c-api-functions">
<h3><a class="toc-backref" href="#c-api-functions" role="doc-backlink">C API functions</a></h3>
<p>We list some relevant Python/C API macros and functions.
Some of these are existing (possibly changed) functions, some are new:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyBaseFunction_CheckFast(PyObject</span> <span class="pre">*op)</span></code>: return true if <code class="docutils literal notranslate"><span class="pre">op</span></code>
is an instance of a class with the <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_BASEFUNCTION</span></code> set.
This is the function that you need to use to determine
whether it is meaningful to access the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> internals.</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyBaseFunction_Check(PyObject</span> <span class="pre">*op)</span></code>: return true if <code class="docutils literal notranslate"><span class="pre">op</span></code>
is an instance of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyBaseFunction_New(PyTypeObject</span> <span class="pre">*cls,</span> <span class="pre">PyCFunctionDef</span> <span class="pre">*ml,</span> <span class="pre">PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*module,</span> <span class="pre">PyObject</span> <span class="pre">*parent)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">cls</span></code> (which must be a subclass of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>)
from the given data.</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyCFunction_Check(PyObject</span> <span class="pre">*op)</span></code>: return true if <code class="docutils literal notranslate"><span class="pre">op</span></code>
is an instance of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyCFunction_NewEx(PyMethodDef*</span> <span class="pre">ml,</span> <span class="pre">PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject*</span> <span class="pre">module)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.
As special case, if <code class="docutils literal notranslate"><span class="pre">self</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,
then set <code class="docutils literal notranslate"><span class="pre">self</span> <span class="pre">=</span> <span class="pre">Py_None</span></code> instead (for backwards compatibility).
If <code class="docutils literal notranslate"><span class="pre">self</span></code> is a module, then <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> is set to <code class="docutils literal notranslate"><span class="pre">self</span></code>.
Otherwise, <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</li>
<li>For many existing <code class="docutils literal notranslate"><span class="pre">PyCFunction_...</span></code> and <code class="docutils literal notranslate"><span class="pre">PyMethod_</span></code> functions,
we define a new function <code class="docutils literal notranslate"><span class="pre">PyBaseFunction_...</span></code>
acting on <code class="docutils literal notranslate"><span class="pre">base_function</span></code> instances.
The old functions are kept as aliases of the new functions.</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyFunction_Check(PyObject</span> <span class="pre">*op)</span></code>: return true if <code class="docutils literal notranslate"><span class="pre">op</span></code>
is an instance of <code class="docutils literal notranslate"><span class="pre">base_function</span></code> with the <code class="docutils literal notranslate"><span class="pre">METH_PYTHON</span></code> flag set
(this is equivalent to checking whether <code class="docutils literal notranslate"><span class="pre">op</span></code> is an instance of <code class="docutils literal notranslate"><span class="pre">function</span></code>).</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyFunction_CheckFast(PyObject</span> <span class="pre">*op)</span></code>: equivalent to
<code class="docutils literal notranslate"><span class="pre">PyFunction_Check(op)</span> <span class="pre">&amp;&amp;</span> <span class="pre">PyBaseFunction_CheckFast(op)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyFunction_CheckExact(PyObject</span> <span class="pre">*op)</span></code>: return true
if the type of <code class="docutils literal notranslate"><span class="pre">op</span></code> is <code class="docutils literal notranslate"><span class="pre">function</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyFunction_NewPython(PyTypeObject</span> <span class="pre">*cls,</span> <span class="pre">PyObject</span> <span class="pre">*code,</span> <span class="pre">PyObject</span> <span class="pre">*globals,</span> <span class="pre">PyObject</span> <span class="pre">*name,</span> <span class="pre">PyObject</span> <span class="pre">*qualname)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">cls</span></code> (which must be a subclass of <code class="docutils literal notranslate"><span class="pre">function</span></code>)
from the given data.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyFunction_New(PyObject</span> <span class="pre">*code,</span> <span class="pre">PyObject</span> <span class="pre">*globals)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">function</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyFunction_NewWithQualName(PyObject</span> <span class="pre">*code,</span> <span class="pre">PyObject</span> <span class="pre">*globals,</span> <span class="pre">PyObject</span> <span class="pre">*qualname)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">function</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyFunction_Copy(PyTypeObject</span> <span class="pre">*cls,</span> <span class="pre">PyObject</span> <span class="pre">*func)</span></code>:
create a new instance of <code class="docutils literal notranslate"><span class="pre">cls</span></code> (which must be a subclass of <code class="docutils literal notranslate"><span class="pre">function</span></code>)
by copying a given <code class="docutils literal notranslate"><span class="pre">function</span></code>.</li>
</ul>
</section>
<section id="changes-to-the-types-module">
<h3><a class="toc-backref" href="#changes-to-the-types-module" role="doc-backlink">Changes to the types module</a></h3>
<p>Two types are added: <code class="docutils literal notranslate"><span class="pre">types.BaseFunctionType</span></code> corresponding to
<code class="docutils literal notranslate"><span class="pre">base_function</span></code> and <code class="docutils literal notranslate"><span class="pre">types.DefinedFunctionType</span></code> corresponding to
<code class="docutils literal notranslate"><span class="pre">defined_function</span></code>.</p>
<p>Apart from that, no changes to the <code class="docutils literal notranslate"><span class="pre">types</span></code> module are made.
In particular, <code class="docutils literal notranslate"><span class="pre">types.FunctionType</span></code> refers to <code class="docutils literal notranslate"><span class="pre">function</span></code>.
However, the actual types will change:
in particular, <code class="docutils literal notranslate"><span class="pre">types.BuiltinFunctionType</span></code> will no longer be the same
as <code class="docutils literal notranslate"><span class="pre">types.BuiltinMethodType</span></code>.</p>
</section>
<section id="changes-to-the-inspect-module">
<h3><a class="toc-backref" href="#changes-to-the-inspect-module" role="doc-backlink">Changes to the inspect module</a></h3>
<p>The new function <code class="docutils literal notranslate"><span class="pre">inspect.isbasefunction</span></code> checks for an instance of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">inspect.isfunction</span></code> checks for an instance of <code class="docutils literal notranslate"><span class="pre">defined_function</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">inspect.isbuiltin</span></code> checks for an instance of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">inspect.isroutine</span></code> checks <code class="docutils literal notranslate"><span class="pre">isbasefunction</span></code> or <code class="docutils literal notranslate"><span class="pre">ismethoddescriptor</span></code>.</p>
<p><strong>NOTE</strong>: bpo-33261 <a class="footnote-reference brackets" href="#bpo33261" id="id6">[3]</a> should be fixed first.</p>
</section>
<section id="profiling">
<h3><a class="toc-backref" href="#profiling" role="doc-backlink">Profiling</a></h3>
<p>Currently, <code class="docutils literal notranslate"><span class="pre">sys.setprofile</span></code> supports <code class="docutils literal notranslate"><span class="pre">c_call</span></code>, <code class="docutils literal notranslate"><span class="pre">c_return</span></code> and <code class="docutils literal notranslate"><span class="pre">c_exception</span></code>
events for built-in functions.
These events are generated when calling or returning from a built-in function.
By contrast, the <code class="docutils literal notranslate"><span class="pre">call</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span></code> events are generated by the function itself.
So nothing needs to change for the <code class="docutils literal notranslate"><span class="pre">call</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span></code> events.</p>
<p>Since we no longer make a difference between C functions and Python functions,
we need to prevent the <code class="docutils literal notranslate"><span class="pre">c_*</span></code> events for Python functions.
This is done by not generating those events if the
<code class="docutils literal notranslate"><span class="pre">METH_PYTHON</span></code> flag in <code class="docutils literal notranslate"><span class="pre">ml_flags</span></code> is set.</p>
</section>
</section>
<section id="non-cpython-implementations">
<h2><a class="toc-backref" href="#non-cpython-implementations" role="doc-backlink">Non-CPython implementations</a></h2>
<p>Most of this PEP is only relevant to CPython.
For other implementations of Python,
the two changes that are required are the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> base class
and the fact that <code class="docutils literal notranslate"><span class="pre">function</span></code> can be subclassed.
The classes <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> and <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> are not required.</p>
<p>We require <code class="docutils literal notranslate"><span class="pre">base_function</span></code> for consistency but we put no requirements on it:
it is acceptable if this is just a copy of <code class="docutils literal notranslate"><span class="pre">object</span></code>.
Support for the new <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> (and <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code>) attribute is not required.
If there is no <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> class,
then <code class="docutils literal notranslate"><span class="pre">types.DefinedFunctionType</span></code> should be an alias of <code class="docutils literal notranslate"><span class="pre">types.FunctionType</span></code>.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<section id="why-not-simply-change-existing-classes">
<h3><a class="toc-backref" href="#why-not-simply-change-existing-classes" role="doc-backlink">Why not simply change existing classes?</a></h3>
<p>One could try to solve the problem by keeping the existing classes
without introducing a new <code class="docutils literal notranslate"><span class="pre">base_function</span></code> class.</p>
<p>That might look like a simpler solution but it is not:
it would require introspection support for 3 distinct classes:
<code class="docutils literal notranslate"><span class="pre">function</span></code>, <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.
For the latter two classes, “introspection support” would mean
at a minimum allowing subclassing.
But we dont want to lose performance, so we want fast subclass checks.
This would require two new flags in <code class="docutils literal notranslate"><span class="pre">tp_flags</span></code>.
And we want subclasses to allow <code class="docutils literal notranslate"><span class="pre">__get__</span></code> for built-in functions,
so we should implement the <code class="docutils literal notranslate"><span class="pre">LOAD_METHOD</span></code> opcode for built-in functions too.
More generally, a lot of functionality would need to be duplicated
and the end result would be far more complex code.</p>
<p>It is also not clear how the introspection of built-in function subclasses
would interact with <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code>.
Having two independent kinds of <code class="docutils literal notranslate"><span class="pre">inspect.signature</span></code> support on the same
class sounds like asking for problems.</p>
<p>And this would not fix some of the other differences between built-in functions
and Python functions that were mentioned in the <a class="reference internal" href="#motivation">motivation</a>.</p>
</section>
<section id="why-text-signature-is-not-a-solution">
<h3><a class="toc-backref" href="#why-text-signature-is-not-a-solution" role="doc-backlink">Why __text_signature__ is not a solution</a></h3>
<p>Built-in functions have an attribute <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code>,
which gives the signature of the function as plain text.
The default values are evaluated by <code class="docutils literal notranslate"><span class="pre">ast.literal_eval</span></code>.
Because of this, it supports only a small number of standard Python classes
and not arbitrary Python objects.</p>
<p>And even if <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code> would allow arbitrary signatures somehow,
that is only one piece of introspection:
it does not help with <code class="docutils literal notranslate"><span class="pre">inspect.getsourcefile</span></code> for example.</p>
</section>
<section id="defined-function-versus-function">
<h3><a class="toc-backref" href="#defined-function-versus-function" role="doc-backlink">defined_function versus function</a></h3>
<p>In many places, a decision needs to be made whether the old <code class="docutils literal notranslate"><span class="pre">function</span></code> class
should be replaced by <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> or the new <code class="docutils literal notranslate"><span class="pre">function</span></code> class.
This is done by thinking of the most likely use case:</p>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">types.FunctionType</span></code> refers to <code class="docutils literal notranslate"><span class="pre">function</span></code> because that
type might be used to construct instances using <code class="docutils literal notranslate"><span class="pre">types.FunctionType(...)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">inspect.isfunction()</span></code> refers to <code class="docutils literal notranslate"><span class="pre">defined_function</span></code>
because this is the class where introspection is supported.</li>
<li>The C API functions must refer to <code class="docutils literal notranslate"><span class="pre">function</span></code> because
we do not specify how the various attributes of <code class="docutils literal notranslate"><span class="pre">defined_function</span></code>
are implemented.
We expect that this is not a problem since there is typically no
reason for introspection to be done by C extensions.</li>
</ol>
</section>
<section id="scope-of-this-pep-which-classes-are-involved">
<h3><a class="toc-backref" href="#scope-of-this-pep-which-classes-are-involved" role="doc-backlink">Scope of this PEP: which classes are involved?</a></h3>
<p>The main motivation of this PEP is fixing function classes,
so we certainly want to unify the existing classes
<code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and <code class="docutils literal notranslate"><span class="pre">function</span></code>.</p>
<p>Since built-in functions and methods have the same class,
it seems natural to include bound methods too.
And since there are no “unbound methods” for Python functions,
it makes sense to get rid of unbound methods for extension types.</p>
<p>For now, no changes are made to the classes <code class="docutils literal notranslate"><span class="pre">staticmethod</span></code>,
<code class="docutils literal notranslate"><span class="pre">classmethod</span></code> and <code class="docutils literal notranslate"><span class="pre">classmethod_descriptor</span></code>.
It would certainly make sense to put these in the <code class="docutils literal notranslate"><span class="pre">base_function</span></code>
class hierarchy and unify <code class="docutils literal notranslate"><span class="pre">classmethod</span></code> and <code class="docutils literal notranslate"><span class="pre">classmethod_descriptor</span></code>.
However, this PEP is already big enough
and this is left as a possible future improvement.</p>
<p>Slot wrappers for extension types like <code class="docutils literal notranslate"><span class="pre">__init__</span></code> or <code class="docutils literal notranslate"><span class="pre">__eq__</span></code>
are quite different from normal methods.
They are also typically not called directly because you would normally
write <code class="docutils literal notranslate"><span class="pre">foo[i]</span></code> instead of <code class="docutils literal notranslate"><span class="pre">foo.__getitem__(i)</span></code>.
So these are left outside the scope of this PEP.</p>
<p>Python also has an <code class="docutils literal notranslate"><span class="pre">instancemethod</span></code> class,
which seems to be a relic from Python 2,
where it was used for bound and unbound methods.
It is not clear whether there is still a use case for it.
In any case, there is no reason to deal with it in this PEP.</p>
<p><strong>TODO</strong>: should <code class="docutils literal notranslate"><span class="pre">instancemethod</span></code> be deprecated?
It doesnt seem used at all within CPython 3.7,
but maybe external packages use it?</p>
</section>
<section id="not-treating-meth-static-and-meth-class">
<h3><a class="toc-backref" href="#not-treating-meth-static-and-meth-class" role="doc-backlink">Not treating METH_STATIC and METH_CLASS</a></h3>
<p>Almost nothing in this PEP refers to the flags <code class="docutils literal notranslate"><span class="pre">METH_STATIC</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_CLASS</span></code>.
These flags are checked only by the <a class="reference internal" href="#automatic-creation-of-built-in-functions">automatic creation of built-in functions</a>.
When a <code class="docutils literal notranslate"><span class="pre">staticmethod</span></code>, <code class="docutils literal notranslate"><span class="pre">classmethod</span></code> or <code class="docutils literal notranslate"><span class="pre">classmethod_descriptor</span></code>
is bound (i.e. <code class="docutils literal notranslate"><span class="pre">__get__</span></code> is called),
a <code class="docutils literal notranslate"><span class="pre">base_function</span></code> instance is created with <code class="docutils literal notranslate"><span class="pre">m_self</span> <span class="pre">!=</span> <span class="pre">NULL</span></code>.
For a <code class="docutils literal notranslate"><span class="pre">classmethod</span></code>, this is obvious since <code class="docutils literal notranslate"><span class="pre">m_self</span></code>
is the class that the method is bound to.
For a <code class="docutils literal notranslate"><span class="pre">staticmethod</span></code>, one can take an arbitrary Python object for <code class="docutils literal notranslate"><span class="pre">m_self</span></code>.
For backwards compatibility, we choose <code class="docutils literal notranslate"><span class="pre">m_self</span> <span class="pre">=</span> <span class="pre">__parent__</span></code> for static methods
of extension types.</p>
</section>
<section id="self-in-base-function">
<h3><a class="toc-backref" href="#self-in-base-function" role="doc-backlink">__self__ in base_function</a></h3>
<p>It may look strange at first sight to add the <code class="docutils literal notranslate"><span class="pre">__self__</span></code> slot
in <code class="docutils literal notranslate"><span class="pre">base_function</span></code> as opposed to <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>.
We took this idea from the existing <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> class.
It allows us to have a single general implementation of <code class="docutils literal notranslate"><span class="pre">__call__</span></code> and <code class="docutils literal notranslate"><span class="pre">__get__</span></code>
for the various function classes discussed in this PEP.</p>
<p>It also makes it easy to support existing built-in functions
which set <code class="docutils literal notranslate"><span class="pre">__self__</span></code> to the module (for example, <code class="docutils literal notranslate"><span class="pre">sys.exit.__self__</span></code> is <code class="docutils literal notranslate"><span class="pre">sys</span></code>).</p>
</section>
<section id="two-implementations-of-doc">
<h3><a class="toc-backref" href="#two-implementations-of-doc" role="doc-backlink">Two implementations of __doc__</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">base_function</span></code> does not support function docstrings.
Instead, the classes <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> and <code class="docutils literal notranslate"><span class="pre">function</span></code>
each have their own way of dealing with docstrings
(and <code class="docutils literal notranslate"><span class="pre">bound_method</span></code> just takes the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> from the wrapped function).</p>
<p>For <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>, the docstring is stored (together with the text signature)
as C string in the read-only <code class="docutils literal notranslate"><span class="pre">ml_doc</span></code> field of a <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code>.
For <code class="docutils literal notranslate"><span class="pre">function</span></code>, the docstring is stored as a writable Python object
and it does not actually need to be a string.
It looks hard to unify these two very different ways of dealing with <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>.
For backwards compatibility, we keep the existing implementations.</p>
<p>For <code class="docutils literal notranslate"><span class="pre">defined_function</span></code>, we require <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> to be implemented
but we do not specify how. A subclass can implement <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> the
same way as <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> or using a struct member or some other way.</p>
</section>
<section id="subclassing">
<h3><a class="toc-backref" href="#subclassing" role="doc-backlink">Subclassing</a></h3>
<p>We disallow subclassing of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> and <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>
to enable fast type checks for <code class="docutils literal notranslate"><span class="pre">PyCFunction_Check</span></code> and <code class="docutils literal notranslate"><span class="pre">PyMethod_Check</span></code>.</p>
<p>We allow subclassing of the other classes because there is no reason to disallow it.
For Python modules, the only relevant class to subclass is
<code class="docutils literal notranslate"><span class="pre">function</span></code> because the others cannot be instantiated anyway.</p>
</section>
<section id="replacing-tp-call-meth-pass-function-and-meth-call-unbound">
<h3><a class="toc-backref" href="#replacing-tp-call-meth-pass-function-and-meth-call-unbound" role="doc-backlink">Replacing tp_call: METH_PASS_FUNCTION and METH_CALL_UNBOUND</a></h3>
<p>The new flags <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code>
are meant to support cases where formerly a custom <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> was used.
It reduces the number of special fast paths in <code class="docutils literal notranslate"><span class="pre">Python/ceval.c</span></code>
for calling objects:
instead of treating Python functions, built-in functions and method descriptors
separately, there would only be a single check.</p>
<p>The signature of <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> is essentially the signature
of <code class="docutils literal notranslate"><span class="pre">PyBaseFunctionObject.m_ml.ml_meth</span></code> with flags
<code class="docutils literal notranslate"><span class="pre">METH_VARARGS</span> <span class="pre">|</span> <span class="pre">METH_KEYWORDS</span> <span class="pre">|</span> <span class="pre">METH_PASS_FUNCTION</span> <span class="pre">|</span> <span class="pre">METH_CALL_UNBOUND</span></code>
(the only difference is an added <code class="docutils literal notranslate"><span class="pre">self</span></code> argument).
Therefore, it should be easy to change existing <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> slots
to use the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> implementation instead.</p>
<p>It also makes sense to use <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> without <code class="docutils literal notranslate"><span class="pre">METH_CALL_UNBOUND</span></code>
in cases where the C function simply needs access to additional metadata
from the function, such as the <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>.
This is for example needed to support <a class="pep reference internal" href="../pep-0573/" title="PEP 573 Module State Access from C Extension Methods">PEP 573</a>.
Converting existing methods to use <code class="docutils literal notranslate"><span class="pre">METH_PASS_FUNCTION</span></code> is trivial:
it only requires adding an extra argument to the C function.</p>
</section>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards compatibility</a></h2>
<p>While designing this PEP, great care was taken to not break
backwards compatibility too much.
Most of the potentially incompatible changes
are changes to CPython implementation details
which are different anyway in other Python interpreters.
In particular, Python code which correctly runs on PyPy
will very likely continue to work with this PEP.</p>
<p>The standard classes and functions like
<code class="docutils literal notranslate"><span class="pre">staticmethod</span></code>, <code class="docutils literal notranslate"><span class="pre">functools.partial</span></code> or <code class="docutils literal notranslate"><span class="pre">operator.methodcaller</span></code>
do not need to change at all.</p>
<section id="changes-to-types-and-inspect">
<h3><a class="toc-backref" href="#changes-to-types-and-inspect" role="doc-backlink">Changes to types and inspect</a></h3>
<p>The proposed changes to <code class="docutils literal notranslate"><span class="pre">types</span></code> and <code class="docutils literal notranslate"><span class="pre">inspect</span></code>
are meant to minimize changes in behaviour.
However, it is unavoidable that some things change
and this can cause code which uses <code class="docutils literal notranslate"><span class="pre">types</span></code> or <code class="docutils literal notranslate"><span class="pre">inspect</span></code> to break.
In the Python standard library for example,
changes are needed in the <code class="docutils literal notranslate"><span class="pre">doctest</span></code> module because of this.</p>
<p>Also, tools which take various kinds of functions as input will need to deal
with the new function hierarchy and the possibility of custom
function classes.</p>
</section>
<section id="python-functions">
<h3><a class="toc-backref" href="#python-functions" role="doc-backlink">Python functions</a></h3>
<p>For Python functions, essentially nothing changes.
The attributes that existed before still exist and Python functions
can be initialized, called and turned into methods as before.</p>
<p>The name <code class="docutils literal notranslate"><span class="pre">function</span></code> is kept for backwards compatibility.
While it might make sense to change the name to something more
specific like <code class="docutils literal notranslate"><span class="pre">python_function</span></code>,
that would require a lot of annoying changes in documentation and testsuites.</p>
</section>
<section id="id7">
<h3><a class="toc-backref" href="#id7" role="doc-backlink">Built-in functions of a module</a></h3>
<p>Also for built-in functions, nothing changes.
We keep the old behaviour that such functions do not bind as methods.
This is a consequence of the fact that <code class="docutils literal notranslate"><span class="pre">__self__</span></code> is set to the module.</p>
</section>
<section id="built-in-bound-and-unbound-methods">
<h3><a class="toc-backref" href="#built-in-bound-and-unbound-methods" role="doc-backlink">Built-in bound and unbound methods</a></h3>
<p>The types of built-in bound and unbound methods will change.
However, this does not affect calling such methods
because the protocol in <code class="docutils literal notranslate"><span class="pre">base_function.__call__</span></code>
(in particular the handling of <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> and self slicing)
was specifically designed to be backwards compatible.
All attributes which existed before (like <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> and <code class="docutils literal notranslate"><span class="pre">__self__</span></code>)
still exist.</p>
</section>
<section id="new-attributes">
<h3><a class="toc-backref" href="#new-attributes" role="doc-backlink">New attributes</a></h3>
<p>Some objects get new special double-underscore attributes.
For example, the new attribute <code class="docutils literal notranslate"><span class="pre">__parent__</span></code> appears on
all built-in functions and all methods get a <code class="docutils literal notranslate"><span class="pre">__func__</span></code> attribute.
The fact that <code class="docutils literal notranslate"><span class="pre">__self__</span></code> is now a special read-only attribute
for Python functions caused trouble in <a class="footnote-reference brackets" href="#bpo33265" id="id8">[4]</a>.
Generally, we expect that not much will break though.</p>
</section>
<section id="method-descriptor-and-pydescr-newmethod">
<h3><a class="toc-backref" href="#method-descriptor-and-pydescr-newmethod" role="doc-backlink">method_descriptor and PyDescr_NewMethod</a></h3>
<p>The class <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code> and the constructor <code class="docutils literal notranslate"><span class="pre">PyDescr_NewMethod</span></code>
should be deprecated.
They are no longer used by CPython itself but are still supported.</p>
</section>
</section>
<section id="two-phase-implementation">
<h2><a class="toc-backref" href="#two-phase-implementation" role="doc-backlink">Two-phase Implementation</a></h2>
<p><strong>TODO</strong>: this section is optional.
If this PEP is accepted, it should
be decided whether to apply this two-phase implementation or not.</p>
<p>As mentioned above, the <a class="reference internal" href="#changes-to-types-and-inspect">changes to types and inspect</a> can break some
existing code.
In order to further minimize breakage, this PEP could be implemented
in two phases.</p>
<section id="phase-one-keep-existing-classes-but-add-base-classes">
<h3><a class="toc-backref" href="#phase-one-keep-existing-classes-but-add-base-classes" role="doc-backlink">Phase one: keep existing classes but add base classes</a></h3>
<p>Initially, implement the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> class
and use it as common base class but otherwise keep the existing classes
(but not their implementation).</p>
<p>In this proposal, the class hierarchy would become:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nb">object</span>
<span class="o">|</span>
<span class="o">|</span>
<span class="n">base_function</span>
<span class="o">/</span> <span class="o">|</span> \
<span class="o">/</span> <span class="o">|</span> \
<span class="o">/</span> <span class="o">|</span> \
<span class="n">cfunction</span> <span class="o">|</span> <span class="n">defined_function</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> \
<span class="o">|</span> <span class="o">|</span> <span class="n">bound_method</span> \
<span class="o">|</span> <span class="o">|</span> \
<span class="o">|</span> <span class="n">method_descriptor</span> <span class="n">function</span>
<span class="o">|</span>
<span class="n">builtin_function_or_method</span>
</pre></div>
</div>
<p>The leaf classes <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code>, <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>,
<code class="docutils literal notranslate"><span class="pre">bound_method</span></code> and <code class="docutils literal notranslate"><span class="pre">function</span></code> correspond to the existing classes
(with <code class="docutils literal notranslate"><span class="pre">method</span></code> renamed to <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>).</p>
<p>Automatically created functions created in modules become instances
of <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code>.
Unbound methods of extension types become instances of <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.</p>
<p>The class <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code> is a copy of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code> except
that <code class="docutils literal notranslate"><span class="pre">__get__</span></code> returns a <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> instead of a
<code class="docutils literal notranslate"><span class="pre">bound_method</span></code>.</p>
<p>The class <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> has the same C structure as a
<code class="docutils literal notranslate"><span class="pre">bound_method</span></code>, but it inherits from <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.
The <code class="docutils literal notranslate"><span class="pre">__func__</span></code> attribute is not mandatory:
it is only defined when binding a <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.</p>
<p>We keep the implementation of the <code class="docutils literal notranslate"><span class="pre">inspect</span></code> functions as they are.
Because of this and because the existing classes are kept,
backwards compatibility is ensured for code doing type checks.</p>
<p>Since showing an actual <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> would affect a lot
of correctly-functioning code,
any deprecations would only appear in the documentation.
Another reason is that it is hard to show warnings for calling <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">t)</span></code>
(but it could be done using <code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code> hacking)
and impossible for <code class="docutils literal notranslate"><span class="pre">type(x)</span> <span class="pre">is</span> <span class="pre">t</span></code>.</p>
</section>
<section id="phase-two">
<h3><a class="toc-backref" href="#phase-two" role="doc-backlink">Phase two</a></h3>
<p>Phase two is what is actually described in the rest of this PEP.
In terms of implementation,
it would be a relatively small change compared to phase one.</p>
</section>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>Most of this PEP has been implemented for CPython at
<a class="reference external" href="https://github.com/jdemeyer/cpython/tree/pep575">https://github.com/jdemeyer/cpython/tree/pep575</a></p>
<p>There are four steps, corresponding to the commits on that branch.
After each step, CPython is in a mostly working state.</p>
<ol class="arabic simple">
<li>Add the <code class="docutils literal notranslate"><span class="pre">base_function</span></code> class and make it a subclass for <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>.
This is by far the biggest step as the complete <code class="docutils literal notranslate"><span class="pre">__call__</span></code> protocol
is implemented in this step.</li>
<li>Rename <code class="docutils literal notranslate"><span class="pre">method</span></code> to <code class="docutils literal notranslate"><span class="pre">bound_method</span></code> and make it a subclass of <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.
Change unbound methods of extension types to be instances of <code class="docutils literal notranslate"><span class="pre">cfunction</span></code>
such that bound methods of extension types are also instances of <code class="docutils literal notranslate"><span class="pre">bound_method</span></code>.</li>
<li>Implement <code class="docutils literal notranslate"><span class="pre">defined_function</span></code> and <code class="docutils literal notranslate"><span class="pre">function</span></code>.</li>
<li>Changes to other parts of Python, such as the standard library and testsuite.</li>
</ol>
</section>
<section id="appendix-current-situation">
<h2><a class="toc-backref" href="#appendix-current-situation" role="doc-backlink">Appendix: current situation</a></h2>
<p><strong>NOTE</strong>:
This section is more useful during the draft period of the PEP,
so feel free to remove this once the PEP has been accepted.</p>
<p>For reference, we describe in detail the relevant existing classes in CPython 3.7.</p>
<p>Each of the classes involved is an “orphan” class
(no non-trivial subclasses nor superclasses).</p>
<section id="builtin-function-or-method-built-in-functions-and-bound-methods">
<h3><a class="toc-backref" href="#builtin-function-or-method-built-in-functions-and-bound-methods" role="doc-backlink">builtin_function_or_method: built-in functions and bound methods</a></h3>
<p>These are of type <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Objects/methodobject.c#L271">PyCFunction_Type</a>
with structure <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Include/methodobject.h#L102">PyCFunctionObject</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyMethodDef</span> <span class="o">*</span><span class="n">m_ml</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Description</span> <span class="n">of</span> <span class="n">the</span> <span class="n">C</span> <span class="n">function</span> <span class="n">to</span> <span class="n">call</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_self</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Passed</span> <span class="k">as</span> <span class="s1">&#39;self&#39;</span> <span class="n">arg</span> <span class="n">to</span> <span class="n">the</span> <span class="n">C</span> <span class="n">func</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_module</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__module__</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">anything</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_weakreflist</span><span class="p">;</span> <span class="o">/*</span> <span class="n">List</span> <span class="n">of</span> <span class="n">weak</span> <span class="n">references</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyCFunctionObject</span><span class="p">;</span>
<span class="n">struct</span> <span class="n">PyMethodDef</span> <span class="p">{</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">ml_name</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">name</span> <span class="n">of</span> <span class="n">the</span> <span class="n">built</span><span class="o">-</span><span class="ow">in</span> <span class="n">function</span><span class="o">/</span><span class="n">method</span> <span class="o">*/</span>
<span class="n">PyCFunction</span> <span class="n">ml_meth</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">C</span> <span class="n">function</span> <span class="n">that</span> <span class="n">implements</span> <span class="n">it</span> <span class="o">*/</span>
<span class="nb">int</span> <span class="n">ml_flags</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Combination</span> <span class="n">of</span> <span class="n">METH_xxx</span> <span class="n">flags</span><span class="p">,</span> <span class="n">which</span> <span class="n">mostly</span>
<span class="n">describe</span> <span class="n">the</span> <span class="n">args</span> <span class="n">expected</span> <span class="n">by</span> <span class="n">the</span> <span class="n">C</span> <span class="n">func</span> <span class="o">*/</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">ml_doc</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__doc__</span> <span class="n">attribute</span><span class="p">,</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="p">};</span>
</pre></div>
</div>
<p>where <code class="docutils literal notranslate"><span class="pre">PyCFunction</span></code> is a C function pointer (there are various forms of this, the most basic
takes two arguments for <code class="docutils literal notranslate"><span class="pre">self</span></code> and <code class="docutils literal notranslate"><span class="pre">*args</span></code>).</p>
<p>This class is used both for functions and bound methods:
for a method, the <code class="docutils literal notranslate"><span class="pre">m_self</span></code> slot points to the object:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">dict</span><span class="p">(</span><span class="n">foo</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span><span class="o">.</span><span class="n">get</span>
<span class="go">&lt;built-in method get of dict object at 0x...&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dict</span><span class="p">(</span><span class="n">foo</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="o">.</span><span class="vm">__self__</span>
<span class="go">{&#39;foo&#39;: 42}</span>
</pre></div>
</div>
<p>In some cases, a function is considered a “method” of the module defining it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">os</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">os</span><span class="o">.</span><span class="n">kill</span>
<span class="go">&lt;built-in function kill&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="o">.</span><span class="vm">__self__</span>
<span class="go">&lt;module &#39;posix&#39; (built-in)&gt;</span>
</pre></div>
</div>
</section>
<section id="method-descriptor-built-in-unbound-methods">
<h3><a class="toc-backref" href="#method-descriptor-built-in-unbound-methods" role="doc-backlink">method_descriptor: built-in unbound methods</a></h3>
<p>These are of type <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Objects/descrobject.c#L538">PyMethodDescr_Type</a>
with structure <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Include/descrobject.h#L53">PyMethodDescrObject</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyDescrObject</span> <span class="n">d_common</span><span class="p">;</span>
<span class="n">PyMethodDef</span> <span class="o">*</span><span class="n">d_method</span><span class="p">;</span>
<span class="p">}</span> <span class="n">PyMethodDescrObject</span><span class="p">;</span>
<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyTypeObject</span> <span class="o">*</span><span class="n">d_type</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">d_name</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">d_qualname</span><span class="p">;</span>
<span class="p">}</span> <span class="n">PyDescrObject</span><span class="p">;</span>
</pre></div>
</div>
</section>
<section id="function-python-functions">
<h3><a class="toc-backref" href="#function-python-functions" role="doc-backlink">function: Python functions</a></h3>
<p>These are of type <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Objects/funcobject.c#L592">PyFunction_Type</a>
with structure <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Include/funcobject.h#L21">PyFunctionObject</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_code</span><span class="p">;</span> <span class="o">/*</span> <span class="n">A</span> <span class="n">code</span> <span class="nb">object</span><span class="p">,</span> <span class="n">the</span> <span class="vm">__code__</span> <span class="n">attribute</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_globals</span><span class="p">;</span> <span class="o">/*</span> <span class="n">A</span> <span class="n">dictionary</span> <span class="p">(</span><span class="n">other</span> <span class="n">mappings</span> <span class="n">won</span><span class="s1">&#39;t do) */</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_defaults</span><span class="p">;</span> <span class="o">/*</span> <span class="n">NULL</span> <span class="ow">or</span> <span class="n">a</span> <span class="nb">tuple</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_kwdefaults</span><span class="p">;</span> <span class="o">/*</span> <span class="n">NULL</span> <span class="ow">or</span> <span class="n">a</span> <span class="nb">dict</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_closure</span><span class="p">;</span> <span class="o">/*</span> <span class="n">NULL</span> <span class="ow">or</span> <span class="n">a</span> <span class="nb">tuple</span> <span class="n">of</span> <span class="n">cell</span> <span class="n">objects</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_doc</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__doc__</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">anything</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_name</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__name__</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">a</span> <span class="n">string</span> <span class="nb">object</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_dict</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__dict__</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">a</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_weakreflist</span><span class="p">;</span> <span class="o">/*</span> <span class="n">List</span> <span class="n">of</span> <span class="n">weak</span> <span class="n">references</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_module</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="vm">__module__</span> <span class="n">attribute</span><span class="p">,</span> <span class="n">can</span> <span class="n">be</span> <span class="n">anything</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_annotations</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Annotations</span><span class="p">,</span> <span class="n">a</span> <span class="nb">dict</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">func_qualname</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">qualified</span> <span class="n">name</span> <span class="o">*/</span>
<span class="o">/*</span> <span class="n">Invariant</span><span class="p">:</span>
<span class="o">*</span> <span class="n">func_closure</span> <span class="n">contains</span> <span class="n">the</span> <span class="n">bindings</span> <span class="k">for</span> <span class="n">func_code</span><span class="o">-&gt;</span><span class="n">co_freevars</span><span class="p">,</span> <span class="n">so</span>
<span class="o">*</span> <span class="n">PyTuple_Size</span><span class="p">(</span><span class="n">func_closure</span><span class="p">)</span> <span class="o">==</span> <span class="n">PyCode_GetNumFree</span><span class="p">(</span><span class="n">func_code</span><span class="p">)</span>
<span class="o">*</span> <span class="p">(</span><span class="n">func_closure</span> <span class="n">may</span> <span class="n">be</span> <span class="n">NULL</span> <span class="k">if</span> <span class="n">PyCode_GetNumFree</span><span class="p">(</span><span class="n">func_code</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span>
<span class="o">*/</span>
<span class="p">}</span> <span class="n">PyFunctionObject</span><span class="p">;</span>
</pre></div>
</div>
<p>In Python 3, there is no “unbound method” class:
an unbound method is just a plain function.</p>
</section>
<section id="method-python-bound-methods">
<h3><a class="toc-backref" href="#method-python-bound-methods" role="doc-backlink">method: Python bound methods</a></h3>
<p>These are of type <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Objects/classobject.c#L329">PyMethod_Type</a>
with structure <a class="reference external" href="https://github.com/python/cpython/blob/2cb4661707818cfd92556e7fdf9068a993577002/Include/classobject.h#L12">PyMethodObject</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">im_func</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="nb">callable</span> <span class="nb">object</span> <span class="n">implementing</span> <span class="n">the</span> <span class="n">method</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">im_self</span><span class="p">;</span> <span class="o">/*</span> <span class="n">The</span> <span class="n">instance</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">bound</span> <span class="n">to</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">im_weakreflist</span><span class="p">;</span> <span class="o">/*</span> <span class="n">List</span> <span class="n">of</span> <span class="n">weak</span> <span class="n">references</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyMethodObject</span><span class="p">;</span>
</pre></div>
</div>
</section>
</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="cython" role="doc-footnote">
<dt class="label" id="cython">[1]<em> (<a href='#id1'>1</a>, <a href='#id3'>2</a>) </em></dt>
<dd>Cython (<a class="reference external" href="http://cython.org/">http://cython.org/</a>)</aside>
<aside class="footnote brackets" id="bpo30071" role="doc-footnote">
<dt class="label" id="bpo30071">[<a href="#id2">2</a>]</dt>
<dd>Python bug 30071, Duck-typing inspect.isfunction() (<a class="reference external" href="https://bugs.python.org/issue30071">https://bugs.python.org/issue30071</a>)</aside>
<aside class="footnote brackets" id="bpo33261" role="doc-footnote">
<dt class="label" id="bpo33261">[<a href="#id6">3</a>]</dt>
<dd>Python bug 33261, inspect.isgeneratorfunction fails on hand-created methods
(<a class="reference external" href="https://bugs.python.org/issue33261">https://bugs.python.org/issue33261</a> and <a class="reference external" href="https://github.com/python/cpython/pull/6448">https://github.com/python/cpython/pull/6448</a>)</aside>
<aside class="footnote brackets" id="bpo33265" role="doc-footnote">
<dt class="label" id="bpo33265">[<a href="#id8">4</a>]</dt>
<dd>Python bug 33265, contextlib.ExitStack abuses __self__
(<a class="reference external" href="https://bugs.python.org/issue33265">https://bugs.python.org/issue33265</a> and <a class="reference external" href="https://github.com/python/cpython/pull/6456">https://github.com/python/cpython/pull/6456</a>)</aside>
<aside class="footnote brackets" id="methoddoc" role="doc-footnote">
<dt class="label" id="methoddoc">[<a href="#id4">5</a>]</dt>
<dd>PyMethodDef documentation (<a class="reference external" href="https://docs.python.org/3.7/c-api/structures.html#c.PyMethodDef">https://docs.python.org/3.7/c-api/structures.html#c.PyMethodDef</a>)</aside>
<aside class="footnote brackets" id="proposal" role="doc-footnote">
<dt class="label" id="proposal">[<a href="#id5">6</a>]</dt>
<dd>PEP proposal: unifying function/method classes (<a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2018-March/049398.html">https://mail.python.org/pipermail/python-ideas/2018-March/049398.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-0575.rst">https://github.com/python/peps/blob/main/peps/pep-0575.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0575.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="#withdrawal-notice">Withdrawal notice</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#new-classes">New classes</a><ul>
<li><a class="reference internal" href="#base-function">base_function</a></li>
<li><a class="reference internal" href="#cfunction">cfunction</a></li>
<li><a class="reference internal" href="#defined-function">defined_function</a></li>
<li><a class="reference internal" href="#function">function</a></li>
<li><a class="reference internal" href="#bound-method">bound_method</a></li>
</ul>
</li>
<li><a class="reference internal" href="#calling-base-function-instances">Calling base_function instances</a><ul>
<li><a class="reference internal" href="#checking-objclass">Checking __objclass__</a></li>
<li><a class="reference internal" href="#flags">Flags</a></li>
<li><a class="reference internal" href="#self-slicing">Self slicing</a></li>
<li><a class="reference internal" href="#meth-pass-function">METH_PASS_FUNCTION</a></li>
<li><a class="reference internal" href="#meth-fastcall">METH_FASTCALL</a></li>
</ul>
</li>
<li><a class="reference internal" href="#automatic-creation-of-built-in-functions">Automatic creation of built-in functions</a><ul>
<li><a class="reference internal" href="#unbound-methods-of-extension-types">Unbound methods of extension types</a></li>
<li><a class="reference internal" href="#built-in-functions-of-a-module">Built-in functions of a module</a></li>
</ul>
</li>
<li><a class="reference internal" href="#further-changes">Further changes</a><ul>
<li><a class="reference internal" href="#new-type-flag">New type flag</a></li>
<li><a class="reference internal" href="#c-api-functions">C API functions</a></li>
<li><a class="reference internal" href="#changes-to-the-types-module">Changes to the types module</a></li>
<li><a class="reference internal" href="#changes-to-the-inspect-module">Changes to the inspect module</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
</ul>
</li>
<li><a class="reference internal" href="#non-cpython-implementations">Non-CPython implementations</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#why-not-simply-change-existing-classes">Why not simply change existing classes?</a></li>
<li><a class="reference internal" href="#why-text-signature-is-not-a-solution">Why __text_signature__ is not a solution</a></li>
<li><a class="reference internal" href="#defined-function-versus-function">defined_function versus function</a></li>
<li><a class="reference internal" href="#scope-of-this-pep-which-classes-are-involved">Scope of this PEP: which classes are involved?</a></li>
<li><a class="reference internal" href="#not-treating-meth-static-and-meth-class">Not treating METH_STATIC and METH_CLASS</a></li>
<li><a class="reference internal" href="#self-in-base-function">__self__ in base_function</a></li>
<li><a class="reference internal" href="#two-implementations-of-doc">Two implementations of __doc__</a></li>
<li><a class="reference internal" href="#subclassing">Subclassing</a></li>
<li><a class="reference internal" href="#replacing-tp-call-meth-pass-function-and-meth-call-unbound">Replacing tp_call: METH_PASS_FUNCTION and METH_CALL_UNBOUND</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a><ul>
<li><a class="reference internal" href="#changes-to-types-and-inspect">Changes to types and inspect</a></li>
<li><a class="reference internal" href="#python-functions">Python functions</a></li>
<li><a class="reference internal" href="#id7">Built-in functions of a module</a></li>
<li><a class="reference internal" href="#built-in-bound-and-unbound-methods">Built-in bound and unbound methods</a></li>
<li><a class="reference internal" href="#new-attributes">New attributes</a></li>
<li><a class="reference internal" href="#method-descriptor-and-pydescr-newmethod">method_descriptor and PyDescr_NewMethod</a></li>
</ul>
</li>
<li><a class="reference internal" href="#two-phase-implementation">Two-phase Implementation</a><ul>
<li><a class="reference internal" href="#phase-one-keep-existing-classes-but-add-base-classes">Phase one: keep existing classes but add base classes</a></li>
<li><a class="reference internal" href="#phase-two">Phase two</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#appendix-current-situation">Appendix: current situation</a><ul>
<li><a class="reference internal" href="#builtin-function-or-method-built-in-functions-and-bound-methods">builtin_function_or_method: built-in functions and bound methods</a></li>
<li><a class="reference internal" href="#method-descriptor-built-in-unbound-methods">method_descriptor: built-in unbound methods</a></li>
<li><a class="reference internal" href="#function-python-functions">function: Python functions</a></li>
<li><a class="reference internal" href="#method-python-bound-methods">method: Python bound methods</a></li>
</ul>
</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-0575.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>