python 装饰器,使用教程,执行顺序解析
装饰器,通常可以用来做一些其他的事情,譬如说:对于已有的函数添加新的功能,前提是不修改已有函数的内部实现。可以用来记录函数的调用情况。可以用来对于结果进行一些处理。。。可以说,装饰器就是提供了在不修改已有代码的基础上,在函数外部添加一些自定义的功能的简洁实现。
python 中的装饰器写起来相对来说是比较简单的,通常是写一个函数,然后 内部定义一些功能的事项,最终通过一个统一的调用进行结果返回,这个结果就是一个统一的函数调用接口,也就是通常说的wrapper
一个简单的装饰器的实现如下:
import functools def trace(func): print "trace" @functools.wraps(func) def wrapper(*args, **kwargs): print "trace1 before" result = func(*args, **kwargs) print "%s :%r, %r, %r" % (func.__name__, args, kwargs, result) print "trace1 after" return result return wrapper @trace def fib(n): if n in (0, 1): return n return fib(n - 2) + fib(n - 1) print fib(3)
这里是打印出了函数调用时的参数情况,并且将结果打印了出来。
对于简单的一个装饰器的执行情况是这样的:(我的理解)
首先,构建:fib = trace(fib)
然后,执行:fib() ==> trace(fib)(*args, **kwargs) ==> wrapper(*args, **kwargs)
对于多个装饰器:
import functools def trace(func): print "trace" @functools.wraps(func) def wrapper(*args, **kwargs): print "trace1 before" result = func(*args, **kwargs) # print "%s :%r, %r, %r" % (func.__name__, args, kwargs, result) print "trace1 after" return result return wrapper def trace2(func): print "trace2" @functools.wraps(func) def wrapper(*args, **kwargs): print "trace2 before" # print "%s :%r, %r, %r" % (func.__name__, args, kwargs, 0) result = func(*args, **kwargs) print "trace2 after" return result return wrapper @trace @trace2 def fib(n): if n in (0, 1): return n return fib(n - 2) + fib(n - 1) print fib(1)
执行结果:
trace2 trace trace1 before trace2 before trace2 after trace1 after 1对于多个装饰器的执行情况是:
首先,构建:fib = trace(trace2(fib)) # 可以这样理解,括号中的不是参数,而是调用的先后顺序
然后,执行:fib() ==> wrapper(*args, **kwargs)
==> 前边操作
==> wrapper2(*args, **kwargs)
==> 后边操作
因此,也就有了上边的打印输出的情况!!!
总结:在wrapper里面的func执行前的操作是和装饰器书写顺序一样的,其他位置的都是和书写顺序相反!
需要注意的是:在多个装饰器共同装饰的时候,注意器顺序。
我的理解是:要分清构建顺序,和执行顺序。
构建顺序,由被装饰函数最近的一个,往上依次构建!
执行顺序,是分为:结果前执行、结果后执行
在结果前执行是从上到下根据装饰器的书写顺序进行的,
在结果后执行是从下到上执行的
这种情况是方法调用时的栈的操作所致!要注意运用
也就是总结里面说的!!!
另外:functools.wraps装饰器是保留了函数原来的名称,模块等一些原来的信息!!!为了规范,注意加上!!