让C扩展类从Python类继承

让C扩展类从Python类继承,python,python-c-api,Python,Python C Api,我有一个Python类AbstractFoo,它使用@abc.abstractmethod来定义两个抽象方法 为了获得更高的性能,大部分工作是在C中作为Python扩展类CFoo实现的,因此我想做的是从AbstractFoo继承该扩展类 然而,我没有找到一种方法来实现这一点,而是走了另一条路:在C中作为“普通”类实现它,并拥有一个类ConcreteFoo(AbstractFoo,CFoo),它继承自抽象Python和扩展类 然而现在ABC的“保护”并没有起作用:即使方法丢失,也没有抛出错误。我在

我有一个Python类
AbstractFoo
,它使用
@abc.abstractmethod
来定义两个抽象方法

为了获得更高的性能,大部分工作是在C中作为Python扩展类
CFoo
实现的,因此我想做的是从
AbstractFoo
继承该扩展类

然而,我没有找到一种方法来实现这一点,而是走了另一条路:在C中作为“普通”类实现它,并拥有一个
类ConcreteFoo(AbstractFoo,CFoo)
,它继承自抽象Python和扩展类

然而现在ABC的“保护”并没有起作用:即使方法丢失,也没有抛出错误。我在中找到了一个解决方案,并添加了一个新的
new
方法,而不是
PyType\u GenericNew
(暂时忽略空部分的引用计数):

但是现在ABC检查总是触发:
TypeError:无法用抽象方法实例化抽象类ConcreteFoo…

但是检查
dir(ConcreteFoo)
会显示它抱怨的方法

有没有一种方法可以让my
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(CFoo, AbstractFoo):
工作


这对于
\uu mro\uuu
来说是有意义的,您可以通过使
寄存器
不是抽象方法来测试这一点。您会发现中第一个基类的方法优先使用。当第一个基类是
AbstractFoo
时,这是一个首先被发现的抽象方法,因此它失败了。

我认为
\uuuuuAbstractMethods\uuuu
是通过
ABCMeta
在创建类型时设置的。因此,您需要确保在定义类型
ConcreteFoo
时调用该元类,而不是
PyType\u type
。不幸的是,您没有显示这段代码…我不知道您的代码是什么意思。未显示的代码几乎就是您使用的基本样板代码。我在上面添加了
ConcreteFoo
的定义和
AbstractFoo
的重要部分——我有点误解,认为您是在用C声明
ConcreteFoo
(例如,使用
PyObject\u调用(PyType\u Type,
)这确实让事情变得更清楚了
register
对于一个抽象方法名来说是一个危险的选择,因为它与。这是正确的并且有效,谢谢。我发现这与直觉相反,因为我希望从lft到右继承工作。为了完整性:您是否碰巧有到官方文档的链接?也许吧(虽然它显然很快就变得非常详细了)。也许可以这样考虑:所有基类中的所有方法仍然存在,它从左到右搜索以找到合适的方法(而不是“方法被添加的新基类覆盖”,我认为这是您所假设的)
class ConcreteFoo(AbstractFoo, CFoo):
class ConcreteFoo(CFoo, AbstractFoo):