Clarify C calling convention for __class_getitem__ in PEP 560 (#643)
This commit is contained in:
parent
abafa90f05
commit
86c2708d7d
53
pep-0560.rst
53
pep-0560.rst
|
@ -206,6 +206,59 @@ the backwards compatibility::
|
||||||
return meta(name, resolved_bases, ns, **kwds)
|
return meta(name, resolved_bases, ns, **kwds)
|
||||||
|
|
||||||
|
|
||||||
|
Using ``__class_getitem__`` in C extensions
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
As mentioned above, ``__class_getitem__`` is automatically a class method
|
||||||
|
if defined in Python code. To define this method in a C extension, one
|
||||||
|
should use flags ``METH_O|METH_CLASS``. For example, a simple way to make
|
||||||
|
an extension class generic is to use a method that simply returns the
|
||||||
|
original class objects, thus fully erasing the type information at runtime,
|
||||||
|
and deferring all check to static type checkers only::
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
/* ... your code ... */
|
||||||
|
} SimpleGeneric;
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
simple_class_getitem(PyObject *type, PyObject *item)
|
||||||
|
{
|
||||||
|
Py_INCREF(type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef simple_generic_methods[] = {
|
||||||
|
{"__class_getitem__", simple_class_getitem, METH_O|METH_CLASS, NULL},
|
||||||
|
/* ... other methods ... */
|
||||||
|
};
|
||||||
|
|
||||||
|
PyTypeObject SimpleGeneric_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"SimpleGeneric",
|
||||||
|
sizeof(SimpleGeneric),
|
||||||
|
0,
|
||||||
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||||
|
.tp_methods = simple_generic_methods,
|
||||||
|
};
|
||||||
|
|
||||||
|
Such class can be used as a normal generic in Python type annotations
|
||||||
|
(a corresponding stub file should be provided for static type checkers,
|
||||||
|
see PEP 484 for details)::
|
||||||
|
|
||||||
|
from simple_extension import SimpleGeneric
|
||||||
|
from typing import TypeVar
|
||||||
|
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
Alias = SimpleGeneric[str, T]
|
||||||
|
class SubClass(SimpleGeneric[T, int]):
|
||||||
|
...
|
||||||
|
|
||||||
|
data: Alias[int] # Works at runtime
|
||||||
|
more_data: SubClass[str] # Also works at runtime
|
||||||
|
|
||||||
|
|
||||||
Backwards compatibility and impact on users who don't use ``typing``
|
Backwards compatibility and impact on users who don't use ``typing``
|
||||||
====================================================================
|
====================================================================
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue