I've been playing around with Cython lately and I came across this error when applying a decorator to a Cython function
Cdef functions/classes cannot take arbitrary decorators
Here is the code I was tinkering with:
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)
The error suggests that cdef functions can only take certain decorators. Is it possible to write your own decorators that you can apply to cdef functions?
EDIT: For future readers:
The g = plus_one(_g)
trick mentioned in @DavidW's answer sort of works. It does not work with recursion. e.g. doing fib = memoize(fib)
in my example code does not memoize the recursive calls to fib, although it does memoize the top-level call. i.e. calling fib(5)
will memoize the result of the fib(5)
call, but it will not memoize the recursive calls (i.e. fib(4), fib(3), fib(2), fib(1)
)
As @DavidW points out, cdef, cpdef
functions are fully determined at compile time; the decoration is a runtime thing and does not update the actual function.
cdef
function_fib
, didfib = memorize(_fib)
and made sure you recursively calledfib
(not_fib
) I think it would work, but you'd add a lot of Python overhead on each call. – Laniferous