在cython中组合多个装饰器

combine multiple decorators in cython

我在 combine multiple decorators in python to a single decorator 上发现了这个有趣的问题。

我想在 Cython 中做同样的事情。通常,我的 Cython 代码如下所示:

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef ar[dtype_t, ndim=2] sma_vec(ar[dtype_t, ndim=2] x, int m):
    cdef int n
    cdef Py_ssize_t i, j
    ...

或喜欢

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cpdef ar[dtype_t, ndim=2] sma_vec(ar[dtype_t, ndim=2] x, int m):
    cdef int n
    cdef Py_ssize_t i, j
    ...

我倾向于在几乎所有地方重复这三个装饰器 @cython.boundscheck(False)@cython.wraparound(False)@cython.cdivision(True)

该页面中给出的常规 Python 的解决方案是

def composed(*decs):
    def deco(f):
        for dec in reversed(decs):
            f = dec(f)
        return f
    return deco

对于 Cython,我尝试执行以下操作:

cdef composed_for_cdef(*decs):
     cdef deco(f):
          for dec in reversed(decs):
              f = dec(f)
           return f
      return deco

cpdef composed_for_cpdef(*decs):
     cpdef deco(f):
          for dec in reversed(decs):
              f = dec(f)
           return f
      return deco

但是我在编译过程中遇到了一个错误:

cdef composed_for_cdef(*decs):
    cdef deco(f):
               ^
------------------------------------------------------------

stat\movavg.pyx:12:16: C function definition not allowed here

我什至尝试了常规 Python 的解决方案(上面给出),但出现错误:

@composed(cython.boundscheck(False), cython.wraparound(False), cython.cdivision(True))
^
------------------------------------------------------------

stat\movavg.pyx:24:0: Cdef functions/classes cannot take arbitrary decorators.

组合装饰器并不是这里的最佳方法。只需添加,

# cython: boundscheck=False
# cython: cdivision=True
# cython: wraparound=False

在你的源文件的 header 中(参见 Cython compiler directives),这些选项将应用于所有已定义的函数。如果需要,可以使用适当的装饰器来覆盖此默认行为。

关于组合装饰器的问题,目前看来Cython不支持。例如,即使使用大部分 python 代码,

cpdef composed_for_cpdef(*decs):
   def deco(f):
       for dec in reversed(decs):
           f = dec(f)
       return f
   return deco

我在使用 Cython 0.22 closures inside cpdef functions not yet supported 编译时遇到错误。