我的应用程序需要有几个从单个基类继承的Cython cdef类,但仍然实现了许多接口。 这些接口将用于对类进行isinstance()检查,以确保它们符合某些接口。
我知道Cython不支持多重继承,但是有任何方法可以实现类似接口的行为。 这似乎是Cython的一个相当明显的限制,我确信我不是唯一遇到这个问题的人。
My application needs to have several Cython cdef classes that inherit from a single base class, but yet still implement many interfaces. These interfaces would be used to do isinstance() checks on the classes to make sure they conform to certain interfaces.
I know Cython doesn't support multiple inheritance, but is there any way at all to implement interface-like behavior. It seems like a rather glaring limitation in Cython and I'm sure I'm not the only person to encounter this problem.
最满意答案
当你面对一个你无法改变但你想要与一个接口关联的基类时,你就像在纯Python中那样完全这样做:你使用抽象基类模块
有两种选择可供选择:
你要么把你的类register为属于一个接口(“抽象基类”),就像我为InterfaceA做的那样,或者 你给你的接口一个__subclasshook__ ,它允许它使用正确的方法来声明任何类,就像我为InterfaceB所做的那样。例:
import abc # define the interfaces as normal (non-Cython) Python classes class InterfaceA(metaclass=abc.ABCMeta): # Python3 syntax. metaclasses are slightly different in python2 pass class InterfaceB(metaclass=abc.ABCMeta): @abc.abstractmethod def useful_function(self): raise NotImplementedError() @classmethod def __subclasshook__(cls,other_cls): if cls is InterfaceB: if any("useful_function" in B.__dict__ for B in C.__mro__): return True return NotImplemented # our Cython class cdef class C: def useful_function(self): return 1 c = C() print(isinstance(c,InterfaceA)) # prints False InterfaceA.register(C) print(isinstance(c,InterfaceA)) # prints True print(isinstance(c,InterfaceB)) # prints TrueYou do it exactly as you would in pure Python when faced with a base class that you can't change but that you want to associate with an interface: you use the abstract base classes module
There's two options to chose from:
you either register your class as belonging to an interface ("abstract base class") like I've done for InterfaceA, or you give your interface a __subclasshook__ that allows it to claim any class with the right methods like I've done for InterfaceB.Example:
import abc # define the interfaces as normal (non-Cython) Python classes class InterfaceA(metaclass=abc.ABCMeta): # Python3 syntax. metaclasses are slightly different in python2 pass class InterfaceB(metaclass=abc.ABCMeta): @abc.abstractmethod def useful_function(self): raise NotImplementedError() @classmethod def __subclasshook__(cls,other_cls): if cls is InterfaceB: if any("useful_function" in B.__dict__ for B in C.__mro__): return True return NotImplemented # our Cython class cdef class C: def useful_function(self): return 1 c = C() print(isinstance(c,InterfaceA)) # prints False InterfaceA.register(C) print(isinstance(c,InterfaceA)) # prints True print(isinstance(c,InterfaceB)) # prints True更多推荐
发布评论