最近 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
関数はコンパイル時に完全に決定されます。装飾は実行時のものであり、実際の機能を更新しません。