Update PEP 575 (#616)
This commit is contained in:
parent
582dfee5d0
commit
1a35c75c3c
280
pep-0575.rst
280
pep-0575.rst
|
@ -18,7 +18,7 @@ built-in functions (implemented in C) and Python functions.
|
|||
Mainly, make built-in functions behave more like Python functions
|
||||
without sacrificing performance.
|
||||
|
||||
A new base class ``basefunction`` is introduced and the various function
|
||||
A new base class ``base_function`` is introduced and the various function
|
||||
classes, as well as ``method`` (renamed to ``bound_method``), inherit from it.
|
||||
|
||||
We also allow subclassing of some of these function classes.
|
||||
|
@ -60,13 +60,13 @@ This is the new class hierarchy for functions and methods::
|
|||
object
|
||||
|
|
||||
|
|
||||
basefunction
|
||||
/ | \
|
||||
/ | \
|
||||
/ | generic_function
|
||||
/ | \
|
||||
builtin_function (*) | \
|
||||
| python_function
|
||||
base_function
|
||||
/ | \
|
||||
/ | \
|
||||
/ | defined_function
|
||||
/ | \
|
||||
builtin_function (*) | \
|
||||
| python_function
|
||||
|
|
||||
bound_method (*)
|
||||
|
||||
|
@ -76,10 +76,10 @@ the others do.
|
|||
There is no difference between functions and unbound methods,
|
||||
while bound methods are instances of ``bound_method``.
|
||||
|
||||
basefunction
|
||||
------------
|
||||
base_function
|
||||
-------------
|
||||
|
||||
The class ``basefunction`` becomes a new base class for all function types.
|
||||
The class ``base_function`` becomes a new base class for all function types.
|
||||
It behaves like the existing ``builtin_function_or_method``
|
||||
with some differences:
|
||||
|
||||
|
@ -94,24 +94,16 @@ with some differences:
|
|||
This is mainly meant to support unbound methods of extension types,
|
||||
replacing ``method_descriptor``.
|
||||
Also ``__qualname__`` will use ``__objclass__`` as namespace
|
||||
(instead of ``__self__``).
|
||||
(instead of ``m_self`` before).
|
||||
|
||||
#. Argument Clinic [#clinic]_ is not supported.
|
||||
|
||||
#. The field ``ml_doc`` and the attributes ``__doc__`` and ``__text_signature__``
|
||||
are gone.
|
||||
|
||||
#. A new flag ``METH_CUSTOM`` for ``ml_flags`` which prevents automatic
|
||||
generation of a ``builtin_function``, see `Automatic creation of built-in functions`_.
|
||||
|
||||
#. A new flag ``METH_ARG0_FUNCTION`` for ``ml_flags``.
|
||||
If this flag is set, the C function stored in ``ml_meth`` will be called with first argument
|
||||
equal to the function object instead of ``__self__``.
|
||||
|
||||
#. A new flag ``METH_ARG0_NO_SLICE`` for ``ml_flags``.
|
||||
If this flag is *not* set and ``__self__`` is not set,
|
||||
then the first positional argument is treated as ``__self__``.
|
||||
For more details, see `Self slicing`_.
|
||||
equal to the function object instead of ``m_self``.
|
||||
|
||||
#. A new flag ``METH_BINDING`` for ``ml_flags`` which only applies to
|
||||
functions of a module (not methods of a class).
|
||||
|
@ -119,6 +111,7 @@ with some differences:
|
|||
of the module.
|
||||
This allows the function to behave more like a Python function
|
||||
as it enables ``__get__``.
|
||||
This flag also enables `Self slicing`_.
|
||||
|
||||
#. A new flag ``METH_PYTHON`` for ``ml_flags``.
|
||||
This flag indicates that this function should be treated as Python function.
|
||||
|
@ -126,12 +119,15 @@ with some differences:
|
|||
against the duck typing philosophy.
|
||||
It is still needed in a few places though, for example `Profiling`_.
|
||||
|
||||
The goal of ``basefunction`` is that it supports all different ways
|
||||
#. A new flag ``METH_CUSTOM`` for ``ml_flags`` which prevents automatic
|
||||
generation of a ``builtin_function``, see `Automatic creation of built-in functions`_.
|
||||
|
||||
The goal of ``base_function`` is that it supports all different ways
|
||||
of calling functions and methods in just one structure.
|
||||
For example, the new flag ``METH_ARG0_FUNCTION``
|
||||
will be used by the implementation of Python functions.
|
||||
|
||||
It is not possible to directly create instances of ``basefunction``
|
||||
It is not possible to directly create instances of ``base_function``
|
||||
(``tp_new`` is ``NULL``).
|
||||
However, it is legal for C code to manually create instances.
|
||||
|
||||
|
@ -157,10 +153,17 @@ These are the relevant C structures::
|
|||
|
||||
Subclasses may extend ``PyCFunctionDef`` with extra fields.
|
||||
|
||||
The Python attribute ``__self__`` returns ``m_self``,
|
||||
except if ``METH_STATIC`` is set.
|
||||
In that case, ``None`` is returned.
|
||||
If ``m_self`` is ``NULL``, then there is no ``__self__`` attribute at all.
|
||||
For that reason, we write either ``m_self`` or ``__self__`` in this PEP
|
||||
with slightly different meanings.
|
||||
|
||||
builtin_function
|
||||
----------------
|
||||
|
||||
This is a copy of ``basefunction``, with the following differences:
|
||||
This is a copy of ``base_function``, with the following differences:
|
||||
|
||||
#. ``m_ml`` points to a ``PyMethodDef`` structure,
|
||||
extending ``PyCFunctionDef`` with an additional ``ml_doc``
|
||||
|
@ -174,38 +177,39 @@ This is a copy of ``basefunction``, with the following differences:
|
|||
const char *ml_doc;
|
||||
} PyMethodDef;
|
||||
|
||||
Note that ``PyMethodDef`` is part of the Python Stable ABI [#ABI]_,
|
||||
so we cannot change this structure.
|
||||
Note that ``PyMethodDef`` is part of the Python Stable ABI [#ABI]_
|
||||
and it is used by most extension modules,
|
||||
so we absolutely cannot change this structure.
|
||||
|
||||
#. Argument Clinic [#clinic]_ is supported.
|
||||
|
||||
The type object is ``PyTypeObject PyCFunction_Type``
|
||||
and we define ``PyCFunctionObject`` as alias of ``PyBaseFunctionObject``.
|
||||
|
||||
generic_function
|
||||
defined_function
|
||||
----------------
|
||||
|
||||
The class ``generic_function`` (a subclass of ``basefunction``) adds
|
||||
The class ``defined_function`` (a subclass of ``base_function``) adds
|
||||
support for various standard attributes which are used in ``inspect``.
|
||||
This would be a good class to use for auto-generated C code, for example produced by Cython [#cython]_.
|
||||
|
||||
The layout of the C structure is as follows::
|
||||
|
||||
PyTypeObject PyGenericFunction_Type;
|
||||
PyTypeObject PyDefinedFunction_Type;
|
||||
|
||||
typedef struct {
|
||||
PyBaseFunctionObject base;
|
||||
PyObject *func_name; /* __name__: string */
|
||||
PyObject *func_qualname; /* __qualname__: string */
|
||||
PyObject *func_doc; /* __doc__: can be anything or NULL */
|
||||
PyObject *func_code; /* __code__: code or NULL */
|
||||
PyObject *func_code; /* __code__: code */
|
||||
PyObject *func_globals; /* __globals__: anything; readonly */
|
||||
PyObject *func_defaults; /* __defaults__: tuple or NULL */
|
||||
PyObject *func_kwdefaults; /* __kwdefaults__: dict or NULL */
|
||||
PyObject *func_annotations; /* __annotations__: dict or NULL */
|
||||
PyObject *func_globals; /* __globals__: anything or NULL; readonly */
|
||||
PyObject *func_closure; /* __closure__: tuple of cell objects or NULL; readonly */
|
||||
PyObject *func_annotations; /* __annotations__: dict or NULL */
|
||||
PyObject *func_dict; /* __dict__: dict or NULL */
|
||||
} PyGenericFunctionObject;
|
||||
} PyDefinedFunctionObject;
|
||||
|
||||
This class adds various slots like ``__doc__`` and ``__code__`` to access the C attributes.
|
||||
The slot ``__name__`` returns ``func_name``.
|
||||
|
@ -218,7 +222,7 @@ possibly only a few fields may be filled in.
|
|||
And ``__defaults__`` is not required to be used for calling the function.
|
||||
|
||||
Apart from adding these extra attributes,
|
||||
``generic_function`` behaves exactly the same as ``basefunction``.
|
||||
``defined_function`` behaves exactly the same as ``base_function``.
|
||||
|
||||
python_function
|
||||
---------------
|
||||
|
@ -227,8 +231,9 @@ This is the class meant for functions implemented in Python,
|
|||
formerly known as ``function``.
|
||||
Unlike the other function types,
|
||||
instances of ``python_function`` can be created from Python code.
|
||||
This is not changed, so we do not describe the details in this PEP.
|
||||
|
||||
The layout of the C structure is almost the same as ``generic_function``::
|
||||
The layout of the C structure is almost the same as ``defined_function``::
|
||||
|
||||
PyTypeObject PyFunction_Type;
|
||||
|
||||
|
@ -237,11 +242,11 @@ The layout of the C structure is almost the same as ``generic_function``::
|
|||
PyObject *func_name; /* __name__: string */
|
||||
PyObject *func_qualname; /* __qualname__: string */
|
||||
PyObject *func_doc; /* __doc__: can be anything or NULL */
|
||||
PyObject *func_code; /* __code__: code or NULL */
|
||||
PyObject *func_code; /* __code__: code */
|
||||
PyObject *func_defaults; /* __defaults__: tuple or NULL */
|
||||
PyObject *func_kwdefaults; /* __kwdefaults__: dict or NULL */
|
||||
PyObject *func_annotations; /* __annotations__: dict or NULL */
|
||||
PyObject *func_globals; /* __globals__: anything or NULL; readonly */
|
||||
PyObject *func_globals; /* __globals__: anything; readonly */
|
||||
PyObject *func_closure; /* __closure__: tuple of cell objects or NULL; readonly */
|
||||
PyObject *func_dict; /* __dict__: dict or NULL */
|
||||
PyCFunctionDef _ml; /* Storage for base.m_ml */
|
||||
|
@ -249,17 +254,21 @@ The layout of the C structure is almost the same as ``generic_function``::
|
|||
|
||||
The only difference is an ``_ml`` field
|
||||
which reserves space to be used by ``base.m_ml``.
|
||||
However, it is not required that ``base.m_ml`` points to ``_ml``.
|
||||
|
||||
The constructor takes care of setting up ``base.m_ml``.
|
||||
In particular, it sets the ``METH_PYTHON`` flag.
|
||||
When constructing an instance of ``python_function`` from ``code`` and ``globals``,
|
||||
an instance is created with ``base.m_ml = &_ml``,
|
||||
``base.m_self = NULL`` and with the ``METH_PYTHON`` flag set.
|
||||
|
||||
To make subclassing easier, we also add a copying constructor:
|
||||
if ``f`` is an instance of ``defined_function`` with the ``METH_PYTHON``
|
||||
flag set, then ``types.FunctionType(f)`` copies ``f``.
|
||||
|
||||
bound_method
|
||||
------------
|
||||
|
||||
The class ``bound_method`` is used for all bound methods,
|
||||
regardless of the class of the underlying function.
|
||||
It adds one new attribute on top of ``basefunction``:
|
||||
It adds one new attribute on top of ``base_function``:
|
||||
``__func__`` points to that function.
|
||||
|
||||
``bound_method`` replaces the old ``method`` class
|
||||
|
@ -267,25 +276,28 @@ which was used only for Python functions bound as method.
|
|||
|
||||
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 ``basefunction``.
|
||||
This may be an already-bound method or simply not an instance of ``base_function``.
|
||||
Therefore, in practice there are two kinds of methods:
|
||||
for arbitrary callables, we use a single fixed ``PyCFunctionDef``
|
||||
structure with the ``METH_ARG0_FUNCTION`` flag set.
|
||||
The C function then calls ``__func__`` with the correct arguments.
|
||||
|
||||
For methods which bind instances of ``basefunction``
|
||||
(more precisely, which have the ``Py_TPFLAGS_BASEFUNCTION`` flag set)
|
||||
that have ``m_self == NULL``,
|
||||
we instead use the ``PyCFunctionDef`` from the original function.
|
||||
In this case, the ``__func__`` attribute is only used to implement various attributes
|
||||
but not for calling the method.
|
||||
- For arbitrary callables, we use a single fixed ``PyCFunctionDef``
|
||||
structure with the ``METH_ARG0_FUNCTION`` flag set.
|
||||
The C function then calls ``__func__`` with the correct arguments.
|
||||
|
||||
When constructing a new method from a ``basefunction``,
|
||||
- For methods which bind instances of ``base_function``
|
||||
(more precisely, which have the ``Py_TPFLAGS_BASEFUNCTION`` flag set)
|
||||
that allow self slicing,
|
||||
we instead use the ``PyCFunctionDef`` from the original function.
|
||||
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``,
|
||||
we check that the ``self`` object is an instance of ``__objclass__``
|
||||
(if such a class was specified) and raise a ``TypeError`` otherwise.
|
||||
|
||||
The C structure is::
|
||||
|
||||
PyTypeObject PyMethod_Type;
|
||||
|
||||
typedef struct {
|
||||
PyBaseFunctionObject base;
|
||||
PyObject *im_func; /* __func__: function implementing the method; readonly */
|
||||
|
@ -293,16 +305,16 @@ The C structure is::
|
|||
|
||||
|
||||
|
||||
Calling basefunction instances
|
||||
==============================
|
||||
Calling base_function instances
|
||||
===============================
|
||||
|
||||
We specify the implementation of ``__call__`` for instances of ``basefunction``.
|
||||
We specify the implementation of ``__call__`` for instances of ``base_function``.
|
||||
|
||||
__objclass__
|
||||
------------
|
||||
|
||||
First of all, if the function has an ``__objclass__`` attribute but
|
||||
``m_self`` is ``NULL`` (this is the case for non-static unbound methods of extension types),
|
||||
``m_self`` is ``NULL`` (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 ``self``) must be an instance of ``__objclass__``.
|
||||
If not, a ``TypeError`` is raised.
|
||||
|
@ -311,31 +323,30 @@ Flags
|
|||
-----
|
||||
|
||||
For convenience, we define a new constant:
|
||||
``METH_CALLSIGNATURE`` combines the flags from ``PyCFunctionDef.ml_flags``
|
||||
``METH_CALLSIGNATURE`` combines all flags from ``PyCFunctionDef.ml_flags``
|
||||
which specify the signature of the C function to be called.
|
||||
It is equal to ::
|
||||
|
||||
METH_NOARGS | METH_O | METH_VARARGS | METH_FASTCALL | METH_KEYWORDS
|
||||
METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS
|
||||
|
||||
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.
|
||||
|
||||
There are two more flags which affect calling functions:
|
||||
``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE``.
|
||||
|
||||
There is one new flag which affects calling functions,
|
||||
namely ``METH_ARG0_FUNCTION``.
|
||||
Some flags are already documented in [#methoddoc]_.
|
||||
We explain the others shortly.
|
||||
We explain the other two shortly.
|
||||
|
||||
Self slicing
|
||||
------------
|
||||
|
||||
If the function has no ``__self__``
|
||||
attribute and none of the flags ``METH_ARG0_FUNCTION``, ``METH_ARG0_NO_SLICE`` nor ``METH_STATIC`` is set,
|
||||
If the function has ``m_self == NULL``
|
||||
and the flag ``METH_ARG0_FUNCTION`` is not set,
|
||||
then the first positional argument (if any)
|
||||
is removed from ``*args`` and instead passed as first argument to the C function.
|
||||
Effectively, the first positional argument is treated as ``__self__``.
|
||||
This process is called "self slicing".
|
||||
This process is called "self slicing" and is meant to support unbound methods.
|
||||
This does not affect keyword arguments.
|
||||
|
||||
METH_FASTCALL
|
||||
|
@ -364,17 +375,10 @@ METH_ARG0_FUNCTION
|
|||
------------------
|
||||
|
||||
If this flag is set, then the first argument to the C function
|
||||
is the function itself (the ``basefunction`` instance) instead of ``__self__``.
|
||||
is the function itself (the ``base_function`` instance) instead of ``m_self``.
|
||||
In this case, the C function should deal with ``__self__``
|
||||
by getting it from the function, for example using ``PyBaseFunction_GET_SELF``.
|
||||
|
||||
METH_ARG0_NO_SLICE
|
||||
------------------
|
||||
|
||||
The flag ``METH_ARG0_NO_SLICE`` disables self slicing.
|
||||
It is not allowed to combine the flags ``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE``.
|
||||
That is not a problem because ``METH_ARG0_FUNCTION`` already disables self slicing.
|
||||
|
||||
|
||||
Automatic creation of built-in functions
|
||||
========================================
|
||||
|
@ -408,7 +412,7 @@ For the case of functions of a module,
|
|||
|
||||
An important consequence is that such functions by default
|
||||
do not become methods when used as attribute
|
||||
(``basefunction.__get__`` only does that if ``__self__`` was unset).
|
||||
(``base_function.__get__`` only does that if ``m_self`` was ``NULL``).
|
||||
One could consider this a bug, but this was done for backwards compatibility reasons:
|
||||
in an initial post on python-ideas [#proposal]_ the concensus was to keep this
|
||||
misfeature of built-in functions.
|
||||
|
@ -425,9 +429,9 @@ New type flag
|
|||
|
||||
A new ``PyTypeObject`` flag (for ``tp_flags``) is added:
|
||||
``Py_TPFLAGS_BASEFUNCTION`` to indicate that instances of this type are
|
||||
functions which can be called as a ``basefunction``.
|
||||
In other words, subclasses of ``basefunction``
|
||||
which follow the implementation from `Calling basefunction instances`_.
|
||||
functions which can be called as a ``base_function``.
|
||||
In other words, subclasses of ``base_function``
|
||||
which follow the implementation from `Calling base_function instances`_.
|
||||
|
||||
This is different from flags like ``Py_TPFLAGS_LIST_SUBCLASS``
|
||||
because it indicates more than just a subclass:
|
||||
|
@ -447,7 +451,7 @@ We add and change some Python/C API functions:
|
|||
is an instance of a type with the ``Py_TPFLAGS_BASEFUNCTION`` set.
|
||||
|
||||
- ``PyObject* PyBaseFunction_New(PyTypeObject *cls, PyCFunctionDef *ml, PyObject *self, PyObject *module, PyTypeObject *objclass)``:
|
||||
create a new instance of ``cls`` (which must be a subclass of ``basefunction``)
|
||||
create a new instance of ``cls`` (which must be a subclass of ``base_function``)
|
||||
from the given data.
|
||||
|
||||
- ``int PyCFunction_Check(PyObject *op)``: return true if ``op``
|
||||
|
@ -456,21 +460,24 @@ We add and change some Python/C API functions:
|
|||
- ``int PyCFunction_NewEx(PyMethodDef* ml, PyObject *self, PyObject* module)``:
|
||||
create a new instance of ``builtin_function``.
|
||||
As special case, if ``self`` is ``NULL``,
|
||||
then set ``self = Py_None`` instead.
|
||||
This is done for backwards compatibility.
|
||||
then set ``self = Py_None`` instead (for backwards compatibility).
|
||||
|
||||
- ``int PyFunction_Check(PyObject *op)``: return true if ``op``
|
||||
is an instance of ``generic_function``.
|
||||
is an instance of ``defined_function``.
|
||||
|
||||
- ``PyPythonFunction_New(PyTypeObject *cls, PyObject *code, PyObject *globals, PyObject *name, PyObject *qualname)``:
|
||||
create a new instance of ``cls`` (which must be a sublass of ``python_function``)
|
||||
from the given data.
|
||||
|
||||
- ``PyObject* PyFunction_New(PyObject *code, PyObject *globals)``:
|
||||
create a new instance of ``python_function``.
|
||||
|
||||
- ``PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals)``:
|
||||
- ``PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)``:
|
||||
create a new instance of ``python_function``.
|
||||
|
||||
- For some existing ``PyCFunction_...`` and ``PyMethod_`` functions,
|
||||
- For many existing ``PyCFunction_...`` and ``PyMethod_`` functions,
|
||||
we define a new function ``PyBaseFunction_...``
|
||||
acting on ``basefunction`` instances.
|
||||
acting on ``base_function`` instances.
|
||||
For backwards compatibility,
|
||||
the old functions are kept as aliases of the new functions.
|
||||
|
||||
|
@ -478,8 +485,8 @@ Changes to the types module
|
|||
---------------------------
|
||||
|
||||
Two types are added: ``types.BaseFunctionType`` corresponding to
|
||||
``basefunction`` and ``types.GenericFunctionType`` corresponding to
|
||||
``generic_function``.
|
||||
``base_function`` and ``types.DefinedFunctionType`` corresponding to
|
||||
``defined_function``.
|
||||
|
||||
Apart from that, no changes to the ``types`` module are made.
|
||||
In particular, ``types.FunctionType`` refers to ``python_function``.
|
||||
|
@ -490,12 +497,16 @@ as ``types.BuiltinMethodType``.
|
|||
Changes to the inspect module
|
||||
-----------------------------
|
||||
|
||||
``inspect.isbasefunction`` checks for an instance of ``basefunction``.
|
||||
``inspect.isbasefunction`` checks for an instance of ``base_function``.
|
||||
|
||||
``inspect.isfunction`` checks for an instance of ``generic_function``.
|
||||
``inspect.isfunction`` checks for an instance of ``defined_function``.
|
||||
|
||||
``inspect.isbuiltin`` checks for an instance of ``builtin_function``.
|
||||
|
||||
``inspect.isroutine`` checks ``isbasefunction`` or ``ismethoddescriptor``.
|
||||
|
||||
Note that bpo-33261 [#bpo33261]_ should be fixed first.
|
||||
|
||||
Profiling
|
||||
---------
|
||||
|
||||
|
@ -528,14 +539,14 @@ Non-CPython implementations
|
|||
===========================
|
||||
|
||||
For other implementations of Python apart from CPython,
|
||||
only the classes ``basefunction``, ``bound_method`` and ``python_function`` are required.
|
||||
only the classes ``base_function``, ``bound_method`` and ``python_function`` are required.
|
||||
The latter two are the only classes which can be instantiated directly
|
||||
from the Python interpreter.
|
||||
We require ``basefunction`` for consistency but we put no requirements on it:
|
||||
We require ``base_function`` for consistency but we put no requirements on it:
|
||||
it is acceptable if this is just a copy of ``object``.
|
||||
Support for the new ``__objclass__`` attribute is not required.
|
||||
If there is no ``generic_function`` type,
|
||||
then ``types.GenericFunctionType`` should be an alias of ``types.FunctionType``.
|
||||
If there is no ``defined_function`` type,
|
||||
then ``types.DefinedFunctionType`` should be an alias of ``types.FunctionType``.
|
||||
|
||||
|
||||
Rationale
|
||||
|
@ -544,7 +555,7 @@ Rationale
|
|||
Why not simply change existing classes?
|
||||
---------------------------------------
|
||||
|
||||
One could try to solve the problem not by introducing a new ``basefunction``
|
||||
One could try to solve the problem not by introducing a new ``base_function``
|
||||
class and changing the class hierarchy, but by just changing existing classes.
|
||||
|
||||
That might look like a simpler solution but it is not:
|
||||
|
@ -572,32 +583,32 @@ 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.
|
||||
|
||||
generic_function versus python_function
|
||||
defined_function versus python_function
|
||||
---------------------------------------
|
||||
|
||||
The names ``generic_function`` and ``python_function``
|
||||
The names ``defined_function`` and ``python_function``
|
||||
were chosen to be different from ``function``
|
||||
because none of the two classes ``generic_function``/``python_function``
|
||||
because none of the two classes ``defined_function``/``python_function``
|
||||
is an obvious candidate to receive the ``function`` name.
|
||||
It also allows to use the word "function" informally without referring
|
||||
to a specific class.
|
||||
|
||||
In many places, a decision needs to be made whether the old ``function`` class
|
||||
should be replaced by ``generic_function`` or ``python_function``.
|
||||
should be replaced by ``defined_function`` or ``python_function``.
|
||||
This is done by thinking of the most likely use case:
|
||||
|
||||
1. ``types.FunctionType`` refers to ``python_function`` because that
|
||||
type might be used to construct instances using ``types.FunctionType(...)``.
|
||||
|
||||
2. ``inspect.isfunction()`` refers to ``generic_function``
|
||||
2. ``inspect.isfunction()`` refers to ``defined_function``
|
||||
because this is the class where introspection is supported.
|
||||
|
||||
3. The C API functions ``PyFunction_New...``
|
||||
refer to ``python_function`` simply because one cannot create instances
|
||||
of ``generic_function``.
|
||||
of ``defined_function``.
|
||||
|
||||
4. The C API functions ``PyFunction_Check`` and ``PyFunction_Get/Set...``
|
||||
refer to ``generic_function`` because all attributes exist for instances of ``generic_function``.
|
||||
refer to ``defined_function`` because all attributes exist for instances of ``defined_function``.
|
||||
|
||||
Scope of this PEP: which classes are involved?
|
||||
----------------------------------------------
|
||||
|
@ -613,7 +624,7 @@ 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``.
|
||||
It would certainly make sense to put these in the ``basefunction``
|
||||
It would certainly make sense to put these in the ``base_function``
|
||||
class hierarchy and unify ``classmethod`` and ``classmethod_descriptor``.
|
||||
However, this PEP is already big enough
|
||||
and this is left as a possible future improvement.
|
||||
|
@ -633,14 +644,29 @@ In any case, there is no reason to deal with it in this PEP.
|
|||
It doesn't seem used at all within CPython 3.7,
|
||||
but maybe external packages use it?
|
||||
|
||||
__self__ in basefunction
|
||||
------------------------
|
||||
Not treating METH_STATIC and METH_CLASS
|
||||
---------------------------------------
|
||||
|
||||
Almost nothing in this PEP refers to the flags ``METH_STATIC`` and ``METH_CLASS``.
|
||||
These flags are checked only by the `Automatic creation of built-in functions`_.
|
||||
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``.
|
||||
For backwards compatibility, we choose ``m_self = __objclass__`` for static methods
|
||||
of extension types.
|
||||
|
||||
__self__ in base_function
|
||||
-------------------------
|
||||
|
||||
It may look strange at first sight to add the ``__self__`` slot
|
||||
in ``basefunction`` as opposed to ``bound_method``.
|
||||
in ``base_function`` as opposed to ``bound_method``.
|
||||
We took this idea from the existing ``builtin_function_or_method`` class.
|
||||
It allows us to have a single general implementation of ``__call__``
|
||||
It allows us to have a single general implementation of ``__call__`` and ``__get__``
|
||||
for the various function classes discussed in this PEP.
|
||||
|
||||
It also makes it easy to support existing built-in functions
|
||||
which set ``__self__`` to the module (for example, ``sys.exit.__self__`` is ``sys``).
|
||||
|
||||
|
@ -671,32 +697,6 @@ Therefore, it should be easy to change existing ``tp_call`` slots
|
|||
to use ``METH_ARG0_FUNCTION``.
|
||||
There is one extra complication though: ``__self__`` must be handled manually.
|
||||
|
||||
Self slicing: METH_ARG0_NO_SLICE
|
||||
--------------------------------
|
||||
|
||||
**TODO**: ``METH_ARG0_NO_SLICE`` will probably be dropped from
|
||||
the PEP since both ``METH_ARG0_FUNCTION`` and ``METH_STATIC``
|
||||
already disable self slicing.
|
||||
|
||||
.. We define "self slicing" to mean slicing off the ``self`` argument of a method
|
||||
from the ``*args`` tuple when an unbound method is called.
|
||||
This ``self`` argument is then passed as first argument to the C function.
|
||||
|
||||
.. The specification of ``METH_ARG0_NO_SLICE`` may seem strange at first.
|
||||
The negation is confusing, but it is done for backwards compatibility:
|
||||
existing methods require self slicing but do not specify a flag for it.
|
||||
|
||||
.. Since ``METH_ARG0_FUNCTION`` is clearly incompatible with self slicing
|
||||
(both use the first argument of the C function),
|
||||
this PEP dictates that ``METH_ARG0_FUNCTION`` disables self slicing.
|
||||
So one may wonder if there is actually a use case for ``METH_ARG0_NO_SLICE``
|
||||
without ``METH_ARG0_FUNCTION``.
|
||||
If not, then one could simply unify those two flags in one flag
|
||||
``METH_ARG0_FUNCTION``.
|
||||
|
||||
.. However, a priori, the flag ``METH_ARG0_NO_SLICE`` is meaningful,
|
||||
so we keep the two flags ``METH_ARG0_FUNCTION`` and ``METH_ARG0_NO_SLICE`` separate.
|
||||
|
||||
User flags: METH_CUSTOM and METH_USRx
|
||||
-------------------------------------
|
||||
|
||||
|
@ -738,7 +738,7 @@ 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
|
||||
because the protocol in ``basefunction.__call__``
|
||||
because the protocol in ``base_function.__call__``
|
||||
(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__``)
|
||||
|
@ -761,6 +761,13 @@ For example, ``__objclass__`` now appears on bound methods too
|
|||
and all methods get a ``__func__`` attribute.
|
||||
We expect that this will not cause problems.
|
||||
|
||||
method_descriptor and PyDescr_NewMethod
|
||||
---------------------------------------
|
||||
|
||||
The classes ``method_descriptor`` and the constructor ``PyDescr_NewMethod``
|
||||
are deprecated and no longer used by CPython itself.
|
||||
They are kept for backwards compatibility though.
|
||||
|
||||
|
||||
Reference Implementation
|
||||
========================
|
||||
|
@ -778,8 +785,8 @@ 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.
|
||||
|
||||
There are a surprisingly large number of classes involved,
|
||||
each of them is an "orphan" class (no non-trivial subclasses nor superclasses).
|
||||
Each of the classes involved is an "orphan" class
|
||||
(no non-trivial subclasses nor superclasses).
|
||||
|
||||
builtin_function_or_method: built-in functions and bound methods
|
||||
----------------------------------------------------------------
|
||||
|
@ -890,7 +897,10 @@ References
|
|||
|
||||
.. [#cython] Cython (http://cython.org/)
|
||||
|
||||
.. [#bpo30071] Python bug 30071 (https://bugs.python.org/issue30071)
|
||||
.. [#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)
|
||||
|
||||
.. [#ABI] PEP 384, Defining a Stable ABI, Löwis (https://www.python.org/dev/peps/pep-0384)
|
||||
|
||||
|
|
Loading…
Reference in New Issue