python 装饰器,使用教程,执行顺序解析

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装饰器是保留了函数原来的名称,模块等一些原来的信息!!!为了规范,注意加上!!

猜你喜欢

转载自blog.csdn.net/hpulfc/article/details/80166031