让 C 扩展 class 继承自 Python class
Have C extension class inherit from Python class
我有一个 Python class AbstractFoo
它使用 @abc.abstractmethod
来定义 2 个抽象方法。
为了提高性能,大部分工作是在 C 中作为 Python 扩展 class CFoo
实现的,所以我想做的是继承该扩展 class 来自 AbstractFoo
.
但是我还没有找到一种方法来做到这一点,而是走了一条不同的路:在 C 中将其实现为 "normal" class 并有一个 class ConcreteFoo(AbstractFoo, CFoo)
继承自摘要 Python 和扩展 class.
但是现在 ABC 的 "protection" 没有启动:即使缺少方法也没有抛出错误。我在 中找到了一个解决方案并添加了一个新的 new
方法而不是 PyType_GenericNew
(暂时忽略 empty_* 部分的引用计数):
static PyObject* CFoo_new(PyTypeObject* type, PyObject*, PyObject*)
{
auto* empty_tuple(PyTuple_New(0));
if (!empty_tuple)
return nullptr;
auto* empty_dict(PyDict_New());
if (!empty_dict)
return nullptr;
return PyBaseObject_Type.tp_new(type, empty_tuple.get(), empty_dict.get());
}
但现在 ABC 检查总是触发:TypeError: Can't instantiate abstract class ConcreteFoo with abstract methods ...
但是检查 dir(ConcreteFoo)
会显示它抱怨的方法。
有没有办法让我的 AbstractFoo
的 ABC 检查子 class 在 C 中实现方法?
编辑:更多代码:
class AbstractFoo(abc.ABC):
@abc.abstractmethod
def register(self):
pass
# ...
#...
class ConcreteFoo(AbstractFoo, CFoo):
def __init__(self, arg):
AbstractFoo.__init__(self)
CFoo.__init__(self, arg)
你必须让CFoo
成为第一垒class。这与 C-API 关系不大,也适用于纯 Python 版本:如果您定义
class CFoo:
def register(self):
return "CFoo.register"
然后
class ConcreteFoo(AbstractFoo, CFoo):
失败,但是
class ConcreteFoo(CFoo, AbstractFoo):
有效。
这在 __mro__
方面是有意义的,您可以通过使 register
不是抽象方法来测试它。你会发现优先使用第一个碱基 class 的方法。当第一个基 class 是 AbstractFoo
时,这个 是 一个最先找到的抽象方法,所以它失败了。
我有一个 Python class AbstractFoo
它使用 @abc.abstractmethod
来定义 2 个抽象方法。
为了提高性能,大部分工作是在 C 中作为 Python 扩展 class CFoo
实现的,所以我想做的是继承该扩展 class 来自 AbstractFoo
.
但是我还没有找到一种方法来做到这一点,而是走了一条不同的路:在 C 中将其实现为 "normal" class 并有一个 class ConcreteFoo(AbstractFoo, CFoo)
继承自摘要 Python 和扩展 class.
但是现在 ABC 的 "protection" 没有启动:即使缺少方法也没有抛出错误。我在 中找到了一个解决方案并添加了一个新的 new
方法而不是 PyType_GenericNew
(暂时忽略 empty_* 部分的引用计数):
static PyObject* CFoo_new(PyTypeObject* type, PyObject*, PyObject*)
{
auto* empty_tuple(PyTuple_New(0));
if (!empty_tuple)
return nullptr;
auto* empty_dict(PyDict_New());
if (!empty_dict)
return nullptr;
return PyBaseObject_Type.tp_new(type, empty_tuple.get(), empty_dict.get());
}
但现在 ABC 检查总是触发:TypeError: Can't instantiate abstract class ConcreteFoo with abstract methods ...
但是检查 dir(ConcreteFoo)
会显示它抱怨的方法。
有没有办法让我的 AbstractFoo
的 ABC 检查子 class 在 C 中实现方法?
编辑:更多代码:
class AbstractFoo(abc.ABC):
@abc.abstractmethod
def register(self):
pass
# ...
#...
class ConcreteFoo(AbstractFoo, CFoo):
def __init__(self, arg):
AbstractFoo.__init__(self)
CFoo.__init__(self, arg)
你必须让CFoo
成为第一垒class。这与 C-API 关系不大,也适用于纯 Python 版本:如果您定义
class CFoo:
def register(self):
return "CFoo.register"
然后
class ConcreteFoo(AbstractFoo, CFoo):
失败,但是
class ConcreteFoo(CFoo, AbstractFoo):
有效。
这在 __mro__
方面是有意义的,您可以通过使 register
不是抽象方法来测试它。你会发现优先使用第一个碱基 class 的方法。当第一个基 class 是 AbstractFoo
时,这个 是 一个最先找到的抽象方法,所以它失败了。