使用Cython装饰器的纯Python:如何在模块级别访问属性

1 投票
2 回答
2296 浏览
提问于 2025-04-17 17:33

我想用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 个回答

2

你应该把你的 @cython.cfunc(相当于 cdef,也就是说只能从C语言调用)换成 @cython.ccall(相当于 cpdef,也就是说可以用慢速的Python调用方式和快速的C调用方式都能访问)。

2

@cython.cfunc 这个装饰器相当于用 cdef 定义一个函数(详细信息可以查看 这里)。这意味着这个函数只能在 C 代码中使用。因此,如果想让这个函数在 Python 中也能使用,就需要去掉 @cython.cfunc

撰写回答