14

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

4

1 に答える 1