我有一个Python类
然而,我没有找到一种方法来做到这一点,于是采用了不同的方法:在C中将其实现为“普通”类,并有一个
然而,现在ABC的“保护”没有起作用:即使缺少方法,也没有抛出错误。我在https://dev59.com/AmIj5IYBdhLWcg3wRjSr#20440259中找到了解决方案,并添加了一个新的
AbstractFoo
,它使用@abc.abstractmethod
定义了2个抽象方法。为了提高性能,大部分工作都是在C中实现的Python扩展类CFoo
中完成的,因此我想要做的是从AbstractFoo
继承该扩展类。然而,我没有找到一种方法来做到这一点,于是采用了不同的方法:在C中将其实现为“普通”类,并有一个
class ConcreteFoo(AbstractFoo, CFoo)
,它从抽象Python和扩展类中继承。然而,现在ABC的“保护”没有起作用:即使缺少方法,也没有抛出错误。我在https://dev59.com/AmIj5IYBdhLWcg3wRjSr#20440259中找到了解决方案,并添加了一个新的
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)
会显示它抱怨的方法。
是否有一种方式可以拥有一个经过ABC检查的AbstractFoo
子类,其中方法是用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)
__abstractmethods__
是在由ABCMeta
创建类型时设置的。因此,当你定义类型ConcreteFoo
而不是PyType_Type
时,你需要确保调用这个元类。不幸的是,你没有展示这一部分的代码... - undefinedConcreteFoo
的定义和AbstractFoo
的重要部分。 - undefinedConcreteFoo
(例如使用PyObject_Call(PyType_Type,...)
)。这样做确实更清晰明了。 - undefinedregister
作为一个抽象方法名是一个危险的选择,因为它与abc
库中对register
名称的使用存在冲突。 - undefined