【问题标题】:Multiple Inheritance in Python C APIPython C API 中的多重继承
【发布时间】:2017-03-28 08:56:46
【问题描述】:

如何使用继承自多种其他类型的 Python C API 创建类型?

Python 文档包含一个从另一种类型继承的类型的示例,但我找不到关于多重继承的示例或提及。

【问题讨论】:

  • 请附上文档的链接,并将其中的相关片段添加到您的问题中。

标签: python c python-2.7 multiple-inheritance python-c-api


【解决方案1】:

C API 不支持多重继承。您必须自己调用 PyType_Type,模拟标准 Python class 语句。这记录在 specifying a base type for an extension type 的 C API 部分下:

PyTypeObject* PyTypeObject.tp_base

指向基类型的可选指针 从哪个类型属性继承。在这个级别,只有一个 支持继承;多重继承需要动态 通过调用元类型创建类型对象。

该字段不被子类型继承(显然),但它默认 到&PyBaseObject_Type(Python 程序员称为 输入object)。

【讨论】:

  • 如果我这样做,我仍然可以将tp_methods 设置为指向一些 C 实现,对吧?
  • @tbodt:不。你基本上没有 C API 的强大功能。您不妨用 Python 编写类,并在其实现中将方法委托给 C 函数:def some_method(self): return some_c_function(self)
  • 没有任何 Python 代码有没有办法做到这一点?
  • @tbodt:您可能自己用PyCFunction_New 构造PyCFunction 对象并将它们插入到您传递给PyType_Type 的字典中。我认为那行得通。如果你这样做,你会进入无证领域。
  • 啊。如果您尝试设置tp_methods,会发生什么不好的事情吗?设置tp_bases 有什么好处吗?
【解决方案2】:

假设您有一个名为 test 的模块,具有以下类:

class A:
    a = 1

class B:
    b = 2

这个想法是创建一个新类C,它继承自AB

import test

class C(test.A, test.B):
    pass

specification on PyTypeObject.tp_base 表示它不支持多个基类,并且您必须“通过调用元类型”来创建类。在本例中,元类型为type,因此可以这样创建类:

from test import A, B

C = type("C", (A, B), {})

将其翻译成 C 很简单,虽然有点冗长:

// 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-29
    • 2017-03-31
    • 2020-12-18
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    相关资源
    最近更新 更多