我最近一直在玩 Cython,在将装饰器应用于 Cython 函数时遇到了这个错误
Cdef functions/classes cannot take arbitrary decorators
这是我正在修改的代码:
import functools
def memoize(f):
computed = {}
@functools.wraps(f)
def memoized_f(main_arg, *args, **kwargs):
if computed.get(main_arg):
return computed[main_arg]
computed[main_arg] = f(main_arg, *args, **kwargs)
return computed[main_arg]
return memoized_f
@memoize
cpdef int fib(int n):
return 1 if n < 2 else fib(n - 1) + fib(n - 2)
该错误表明 cdef 函数只能采用某些装饰器。是否可以编写可以应用于 cdef 函数的自己的装饰器?
编辑:对于未来的读者:
g = plus_one(_g)
@DavidW 的回答中提到的技巧很有效。它不适用于递归。例如,fib = memoize(fib)
在我的示例代码中执行的操作不会记住对 fib 的递归调用,尽管它确实会记住顶级调用。即调用fib(5)
将记住调用的结果fib(5)
,但它不会记住递归调用(即fib(4), fib(3), fib(2), fib(1)
)
正如@DavidW 指出的那样,cdef, cpdef
函数在编译时完全确定;装饰是运行时的事情,不会更新实际功能。