python 装饰器(复杂一点的)

装饰器就是为了在不改变函数代码的情况下为函数添加新的功能

实例

def note(func):
    "note function"
    print('note')
    def wrapper(x1,x2):
        "wrapper function"
        print(x1)
        print(x2)
        print('note something')
        # func(x1,x2)
        return func(x1,x2)

    return wrapper

@note   #test=note(test)
def test(a1,a2):
    "test function"
    print('I am test')


test(3,5)  #note(test)()
# print(test.__doc__)

 

带参数的装饰器,在普通装饰器外边再套一个函数,实现可以传递额外参数
import time
def time_logger(flag=0):
    def show_time(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print(end_time-start_time)

            if flag:
                print('将这个操作记录到日志中')
        return wrapper

    return show_time
@time_logger(1)
def add(*args,**kwargs):
    time.sleep(1)
    sum=0
    for i in args:
        sum+=i
    print(sum)

add(1,5,9)

多层装饰器
装饰器函数的执行顺序分为(被装饰函数)定义阶段和(被装饰函数)执行阶段
在被装饰函数定义阶段,执行顺序是从最靠近函数的装饰器开始,自内而外执行
在被装饰函数执行阶段,执行顺序由外而内
需要注意的是,装饰器函数在被装饰器函数定义好的时候就立即执行了
def A(fn):
    print('执行A')
    def inner1():
        print('开始执行inner1')
        fn()
        print('结束inner1')
    return inner1

def B(fn):
    print('执行B')
    def inner2():
        print('开始执行inner2')
        fn()
        print('结束inner2')
    return inner2

@A
@B
def hello():   #A(B(hello))
    print('hello')

hello()

执行B
执行A
开始执行inner1
开始执行inner2
hello
结束inner2
结束inner1

 

类装饰器
需要依靠类内部的__call__方法
import time
class Foo:
    def __init__(self,func):
        self.func=func
    def __call__(self, *args, **kwargs):
        start_time=time.time()
        self.func()
        end_time=time.time()
        print(end_time-start_time)
@Foo    #bar=Foo(bar)
def bar():
    print('bar')
    time.sleep(1)
bar()   #Foo(bar)()

 

functools.wraps,用于解决装饰器的副作用
import functools
def foo():
    print('hello foo')
print(foo.__name__)
def C(func):
    # @functools.wraps(func)    能把原函数的原信息拷贝到装饰器函数中,解决装饰器的副作用
    def inner(*args,**kwargs):
        print(func.__name__+'!!!!!')
        return func(*args,**kwargs)
    return inner
@C
def cal(x):
    return x+x*x
print(cal(2))
print(cal.__name__)
# foo
# cal!!!!!
# 6
# inner  这时的cal.__name__变成装饰器内部函数的名称了

 



posted @ 2019-01-06 19:41  平常心u  阅读(259)  评论(0编辑  收藏  举报