然后给大家介绍的是Wrapper(装饰器),使用广泛。python笔试,面试的话也会百分百问到的,基础和中级的知识储备还是必用的。
让我们开始。
先来一些基础相关知识
*args,**kwargs的区别def function(x,y,*args,**kwargs): print(type(x)) print(args) print(kwargs) print(type(args)) print(type(kwargs))function(1,2,3,4,5,a=1,b=2,c=3)(3, 4, 5) #*args返回的是数组{ 'a': 1, 'c': 3, 'b': 2} #**kwargs返回的字典
正题开始
固定模板
装饰器:wrapper模板:def 装饰器名(func): #def 与 @之后的函数名称一致 调用函数func与ret=func(*args,**kwargs)内部函数一致 def wrapper(*args,**kwargs): #def 与 return 之后的函数名称一致 ret = func(*args,**kwargs) return ret #return ret 与 ret=func(*args,**kwargs)一致 return wrapper@装饰器名def foo(): pass
import timedef timmer(fun1): def wrapper(*args,**kwargs): start_time=time.time() res=fun1(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper@timmerdef foo(): time.sleep(3) print('from foo')@timmerdef foo1(): time.sleep(5) print('from foo1')foo()foo1()
@wraps:避免被装饰函数自身的信息丢失
未添加@wraps
#-*- coding:utf-8 -*-def decorator(func): def inner_function(): pass return inner_function@decoratordef func(): passprint(func.__name__)#inner_function
添加@wraps
from functools import wrapsdef decorator(func): @wraps(func) def inner_function(): pass return inner_function@decoratordef func(): passprint(func.__name__)#func#@wraps:避免被装饰函数自身的信息丢失
多个装饰器的同时使用
def makebold(f): return lambda:''+f()+''def makeitalic(f): return lambda:''+f()+''def makeitalic1(f): return lambda:''+f()+''@makebold@makeitalic1@makeitalicdef say(): return 'hello'print(say())#hello#多个装饰器的执行顺序:是从近到远依次执行。
类装饰器
#类装饰器class Decorator(object): def __init__(self, f): self.f = f def __call__(self): print("decorator start") self.f() print("decorator end")@Decoratordef func(): print("func")func()'''decorator startfuncdecorator end'''
import timedef decorator(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() print(end_time - start_time) return wrapperclass Method(object): @decorator def func(self): time.sleep(0.8)p1 = Method()p1.func() # 函数调用'''0.815999984741对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数- me_instance(任意参数)就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。'''
较为复杂的多个装饰器
import timedef deco01(func): def wrapper(*args, **kwargs): print("this is deco01") startTime = time.time() func(*args, **kwargs) endTime = time.time() msecs = (endTime - startTime)*1000 print("time is %d ms" %msecs) print("deco01 end here") return wrapperdef deco02(func): def wrapper(*args, **kwargs): print("this is deco02") func(*args, **kwargs) print("deco02 end here") return wrapper@deco01@deco02def func(a,b): print("hello,here is a func for add :") time.sleep(1) print("result is %d" %(a+b))if __name__ == '__main__': f = func f(3,4)'''this is deco01this is deco02hello,here is a func for add :result is 7deco02 end heretime is 1032 msdeco01 end here'''#多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。