我有一个Python类AbstractFoo
,它使用@abc.abstractmethod
定义2个抽象方法。
为了获得更高的性能,大部分工作都在C中作为Python扩展类CFoo
实现,所以我想做的就是从AbstractFoo
继承该扩展类。
但是我还没有找到一种方法来做这件事,而是走了一条不同的路线:将其作为C中的“普通”类实现,并具有一个class ConcreteFoo(AbstractFoo, CFoo)
,该类继承自抽象的Python和扩展类。
但是现在,美国广播公司的“保护”措施并未生效:即使缺少这些方法,也不会引发任何错误。我在https://stackoverflow.com/a/20440259/1930508中找到了一个解决方案,并添加了一个新的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检查的子类,其中方法是在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
设为第一基类。这与C-API无关,也适用于纯Python版本:如果您定义
class CFoo:
def register(self):
return "CFoo.register"
然后
class ConcreteFoo(AbstractFoo, CFoo):
失败,但是
class ConcreteFoo(CFoo, AbstractFoo):
作品。
就__mro__
而言,这很有意义,您可以通过使register
不是抽象方法来进行测试。您会发现优先使用第一个基类的方法。当第一个基类为AbstractFoo
时,此is首先被发现的抽象方法,因此它失败。