使用Cython装饰器的纯Python:如何在模块级别访问属性
我想用Cython装饰器写一些纯Python代码,但当我把我的NONE.PY文件改名为NONE.PYX时,出现了错误。为了绕过这个问题,我需要用纯Python的定义来包裹每个属性,而不使用装饰器。我想知道这是为什么……
这里是模块none.pyx(如果你把它改名为none.py,就不会有任何问题)
import cython
@cython.cfunc
@cython.returns(cython.double)
@cython.locals(n=cython.int,i=cython.int,r=cython.int)
def ccrange(n):
r=0
for i in range(n):
r+=i
return r
def crange(n): return ccrange(n)
还有Python测试文件test_none.py:
import pyximport; pyximport.install()
import none
n=10000
print ">>pure python call>>",none.crange(n)
print ">>cython call>>",none.ccrange(n)
使用none.pyx的结果:
纯Python调用>> 49995000.0
Cython调用>>
错误追踪(最近的调用在最前面):
文件 "C:\Users\damien\python4d\bacoland\test_none.py",第6行,
print ">>Cython调用>>",none.ccrange(n)
AttributeError: 'module'对象没有属性'ccrange'
把none.pyx改名为none.py,结果是:
纯Python调用>> 49995000
Cython调用>> 49995000
谢谢你的帮助!祝你有个愉快的一天 :-)
编辑:
避免使用装饰器@cython.cfunc会破坏Cython的速度优势……考虑下面这段代码,分别使用和不使用@cython.cfunc:
@cython.cfunc
@cython.returns(cython.double)
@cython.locals(n=cython.int)
def fibo_c(n):
if n == 0 or n == 1:
return n
return fibo_c(n-2) + fibo_c(n-1)
2 个回答
你应该把你的 @cython.cfunc
(相当于 cdef
,也就是说只能从C语言调用)换成 @cython.ccall
(相当于 cpdef
,也就是说可以用慢速的Python调用方式和快速的C调用方式都能访问)。
@cython.cfunc
这个装饰器相当于用 cdef
定义一个函数(详细信息可以查看 这里)。这意味着这个函数只能在 C
代码中使用。因此,如果想让这个函数在 Python 中也能使用,就需要去掉 @cython.cfunc
。