python - cython cdef 类的多重继承
问题描述
我有一些cdef class
在 cython 中实现的类。在客户端 python 代码中,我想组合具有多重继承的类,但我遇到了类型错误。这是一个最小的可重现示例:
In [1]: %load_ext cython
In [2]: %%cython
...: cdef class A:
...: cdef int x
...: def __init__(self):
...: self.x = 0
...: cdef class B:
...: cdef int y
...: def __init__(self):
...: self.y = 0
...:
In [3]: class C(A, B):
...: pass
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-83ef5091d3a6> in <module>()
----> 1 class C(A, B):
2 pass
TypeError: Error when calling the metaclass bases
multiple bases have instance lay-out conflict
有没有办法解决这个问题?
文档说:
一个 Python 类可以从多个扩展类型继承,前提是遵循多继承的常用 Python 规则(即所有基类的 C 布局必须兼容)。
鉴于上面的简单示例,我试图理解这可能意味着什么。
解决方案
很受限制。尽我所能告诉所有人,除了其中一个类必须是空的。空类可以有def
函数,但不能有cdef
函数或cdef
属性。
参加 Cython 课程:
cdef class A:
cdef int x
这转换为 C 代码:
struct __pyx_obj_2bc_A { // the name might be different
PyObject_HEAD
int x;
};
本质上只是一个包含基本 Python 对象的 C 结构和一个整数。限制是派生类必须只包含一个PyObject_HEAD
,并且它PyObject*
也应该可以解释为 astruct __pyx_obj_2bc_A*
或 a struct __pyx_obj_2bc_B*
。
在您的情况下,这两个整数x
会y
尝试占用相同的内存(因此冲突)。但是,如果其中一种类型为空,那么它们将共享PyObject_HEAD
但不会进一步冲突。
cdef
函数导致 astruct __pyx_vtabstruct_2bc_A *__pyx_vtab;
添加到结构中(因此它不是空的)。这包含允许继承的类覆盖函数的函数指针cdef
。
有两个cdef
继承自公共第三类的类是可以的,如果公共第三类不为空,则事件。
cdef class A:
cdef int x
cdef class B(A):
cdef int y
cdef class C(A):
pass
class D(B,C):
pass
best_base
如果您真的想研究算法的细节,那么执行此检查的内部 Python 代码就是该函数。
关于“有什么办法可以解决这个问题吗?” 答案是“不是真的”。您最好的选择可能是组合而不是继承(即让类C
持有一个A
andB
对象,而不是从A
and继承B
)
推荐阅读
- javascript - 如何停止收到此错误对预检请求的响应未通过访问控制检查
- cordova - cordova playGamesServices 从排行榜获取用户分数
- java - 使用 Java 在 MongoDB 上迭代聚合
- sql - Vertica/SQL,大小写语法
- powershell - PowerShell 模块中是否存在检查函数
- deep-learning - 用两个完全不同的数据集训练神经网络。
- r - 在一个包中包括 shinyBS
- wordpress - Wordpress 按 DESC 对自定义字段整数排序,按 ASC 对小数排序
- c# - 输入上的可选数据属性 [Html]
- c# - 如何创建 SHA1WithRSA 签名