具有C扩展类从Python类继承

问题描述 投票:2回答:1

我有一个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)
python python-c-api
1个回答
0
投票

您必须将CFoo设为第一基类。这与C-API无关,也适用于纯Python版本:如果您定义

class CFoo:
    def register(self):
        return "CFoo.register"

然后

class ConcreteFoo(AbstractFoo, CFoo):

失败,但是

class ConcreteFoo(CFoo, AbstractFoo):

作品。

__mro__而言,这很有意义,您可以通过使register不是抽象方法来进行测试。您会发现优先使用第一个基类的方法。当第一个基类为AbstractFoo时,此is首先被发现的抽象方法,因此它失败。

© www.soinside.com 2019 - 2024. All rights reserved.