python面试之装饰器

import functools

def a(f):
    print('a')

    @functools.wraps(f)
    def wraps(*args, **kwargs):
        print('wraps')
        return f(*args, **kwargs)
    return wraps

@a
def b():
    print('b')

b()
b()

第二次调用b()函数,并没有输出’a’,其实调用b(),b()相当于

import functools

def a(f):
    print('a')

    @functools.wraps(f)
    def wraps(*args, **kwargs):
        print('wraps')
        return f(*args, **kwargs)
    return wraps

def b():
    print('b')


b = a(b)                 //此时打印'a'
b()
b()



# 当导入b的时候装饰器已经运行,而不是自己原以为的调用b时装饰器才运行
In [1]: from t1 import b
a

update_wrapper是wraps的主要功能提供者,它负责考贝原函数的属性,默认是:’module‘, ‘name‘, ‘doc‘, ‘dict

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 


# 通过wraps和update_wrapper实现结果是一致的
In [28]: from functools import wraps, update_wrapper

In [29]: def time1(func):
    ...:     @wraps(func)
    ...:     def wrapper(*args, **kwargs):
    ...:         start = time.time()
    ...:         func(*args, **kwargs)
    ...:         end = time.time()
    ...:         print(func.__name__, end-start)
    ...:     return wrapper
    ...: 

In [30]: def time2(func):
    ...:     
    ...:     def wrapper(*args, **kwargs):
    ...:         start = time.time()
    ...:         func(*args, **kwargs)
    ...:         end = time.time()
    ...:         print(func.__name__, end-start)
    ...:     return update_wrapper(wrapper,func)
    ...: 
    ...: 

In [31]: @time1
    ...: def fori():
    ...:     for i in range(1000):
    ...:         pass
    ...:     

In [32]: fori()