装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。简而言之,修饰器封装一个函数,并且用这样或者那样的方式来修改它的行为,使得在这个函数运行之前或者之后执行某些动作。具体了解可以看这一篇博客:Python 函数装饰器,这一部分内容就转载于此。
为什么可以实现这样的操作呢?因为对于某个定义后的函数 def func(),当使用它时不加括号即func 是不会执行的,只有func()时函数才会被执行,因此我们可以通过函数名func进行随意的传递,也是函数的引用了。
一个简单直接的修饰器的实现
def a_new_decorator(a_func): def wrapTheFunction(): print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()") return wrapTheFunction def a_function_requiring_decoration(): print("I am the function which needs some decoration to remove my foul smell") a_function_requiring_decoration() #outputs: "I am the function which needs some decoration to remove my foul smell" a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) # 被修饰器修饰了的函数 #now a_function_requiring_decoration is wrapped by wrapTheFunction() a_function_requiring_decoration() # 修饰之后被修饰的函数在执行前和后都被添加了新动作。 #outputs:I am doing some boring work before executing a_func() # I am the function which needs some decoration to remove my foul smell # I am doing some boring work after executing a_func()看到这里可能疑问为什么还没有看到修饰器符号,那么现在我们使用 @ 来运行之前的代码:
@a_new_decorator def a_function_requiring_decoration(): """Hey you! Decorate me!""" print("I am the function which needs some decoration to " "remove my foul smell") a_function_requiring_decoration() # 注意!!! 装饰器里返回的仅仅是函数名,如果想执行,必须加上括号 () #outputs: I am doing some boring work before executing a_func() # I am the function which needs some decoration to remove my foul smell # I am doing some boring work after executing a_func() #the @a_new_decorator is just a short way of saying: a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)如果我们运行如下代码会存在一个问题:
print(a_function_requiring_decoration.__name__) # Output: wrapTheFunction这并不是我们想要的!Ouput输出应该是"a_function_requiring_decoration"。这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
from functools import wraps def a_new_decorator(a_func): @wraps(a_func) def wrapTheFunction(): print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()") return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): """Hey yo! Decorate me!""" print("I am the function which needs some decoration to " "remove my foul smell") print(a_function_requiring_decoration.__name__) # Output: a_function_requiring_decoration@cython.boundscheck(False) # Cython默认进行数组越界检查,这也是个降低速度的地方,不过可以用@cython.boundscheck(False)的方法关闭该功能
@cython.wraparound(False) # @cython.wraparound(False) 消除了相对数组尾部的负数下标的处理(类似Python列表)# wrap around:环绕
eg. 看如下的一个代码:
@cython.boundscheck(False) @cython.wraparound(False) def scalar_value_clipped(float[:, :] field, float x, float y): x = clip(x, 0.0, field.shape[1] - 1) y = clip(y, 0.0, field.shape[0] - 1) return field[<Py_ssize_t>y, <Py_ssize_t>x] # Py_ssize_t 是一个所占字节数与 size_t 相同的有符号的整数类型