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