在python中,我使用classmethods作为工厂函数,例如拆分URI并构造适当的(子)类实例。但是,当尝试通过augmenting pxd
将其移植到Cython时,这不起作用。将类定义为cdef class
会给出以下错误:
TypeError: descriptor '<class method name>' of '<cdef class type>' object needs an argument
最小(不是)工作示例:
考虑定义:
# cy.py
class Foo(object):
def imeth(self):
print('i', self)
@classmethod
def cmeth(cls):
print('c', cls)
在python中运行它可以正常工作:
ipython -c 'import cy; cy.Foo().imeth(); cy.Foo().cmeth(); cy.Foo.cmeth()'
('i', <cy.Foo object at 0x100652d50>) # method on instance
('c', <class 'cy.Foo'>) # class method on instance
('c', <class 'cy.Foo'>) # class method on class
只需打开Cython也可以:
ipython -c 'import pyximport; pyximport.install(pyimport = True);import cy; cy.Foo().imeth(); cy.Foo().cmeth(); cy.Foo.cmeth()'
# compiler warnings about unused functions
('i', <cy.Foo object at 0x10b8d7f28>) # method on instance
('c', <class 'cy.Foo'>) # class method on instance
('c', <class 'cy.Foo'>) # class method on class
现在,为pxd
定义添加cdef class
后......
# cy.pxd
cdef class Foo:
cpdef imeth(self)
cpdef cmeth(cls)
...使用Cython(清除缓存后)不再有效:
ipython -c 'import pyximport; print(pyximport.install(pyimport = True));import cy;cy.Foo().imeth(); cy.Foo().cmeth(); cy.Foo.cmeth()'
# compiler warnings about unused functions
i <cy.Foo object at 0x10b742510>
c <cy.Foo object at 0x10b742510>
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-ede0f6764b14> in <module>()
----> 1 import pyximport; print(pyximport.install(pyimport = True));import cy; print(cy);cy.Foo().imeth(); cy.Foo().cmeth(); cy.Foo.cmeth()
TypeError: descriptor 'cmeth' of 'cy.Foo' object needs an argument
第二个输出行显示Foo.cmeth
基本上忽略了classmethod
装饰器。但我似乎无法在pxd
中应用它。这可以通过pxd
首先实现吗?