问题
How do I create a type using the Python C API that inherits from multiple other types?
The Python documentation includes an example of a type that inherits from one other type, but there is no example or mention of multiple inheritance I could find.
回答1:
The C API does not support multiple inheritance. You'd have to call PyType_Type
yourself, simulating a standard Python class
statement. This is documented under the C API section on specifying a base type for an extension type:
PyTypeObject* PyTypeObject.tp_base
An optional pointer to a base type from which type properties are inherited. At this level, only single inheritance is supported; multiple inheritance require dynamically creating a type object by calling the metatype.
This field is not inherited by subtypes (obviously), but it defaults to
&PyBaseObject_Type
(which to Python programmers is known as the typeobject
).
回答2:
Let's say you have a module named test
, with the following classes:
class A:
a = 1
class B:
b = 2
And the idea is to create a new class C
which inherits from A
and B
:
import test
class C(test.A, test.B):
pass
The specification on PyTypeObject.tp_base says that it does not support multiple bases classes and that you have to create the class "by calling the metatype". In this case, the metatype is type, so the class can be created this way:
from test import A, B
C = type("C", (A, B), {})
Translating that to C is straightforward, although a bit verbose:
// from test import A, B
PyObject* test_module = PyImport_ImportModuleNoBlock("test");
if (test_module == NULL) return NULL;
PyObject* ClassA = PyObject_GetAttrString(test_module, "A");
if (ClassA == NULL) return NULL;
PyObject* ClassB = PyObject_GetAttrString(test_module, "B");
if (ClassB == NULL) return NULL;
// name, bases, classdict = "C", (A, B), {}
PyObject *name = PyUnicode_FromString("C");
if (name == NULL) return NULL;
PyObject *bases = PyTuple_Pack(2, ClassA, ClassB);
if (bases == NULL) return NULL;
PyObject *classdict = PyDict_New();
if (dict == NULL) return NULL;
// C = type(name, bases, classdict)
PyObject *ClassC = PyObject_CallObject(
(PyObject*)&PyType_Type, PyTuple_Pack(3, name, bases, classdict));
if (ClassC == NULL) return NULL;
if (PyModule_AddObject(m, "C", ClassC)) return NULL;
来源:https://stackoverflow.com/questions/40593529/multiple-inheritance-in-python-c-api