1. 装饰器的原理以及为什么要使用装饰器
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
在不影响原代码结构的情况下为其添加功能
2. 装饰器的基本用法
def test(func): def warpper(*args,**kwargs): print("====start====") func(*args,**kwargs) print("=====end====") return warpper @test def f(): print("2018-06-04") f()
3. 带参数的装饰器
def test(m): #获取参数 def inner(func): def warpper(*args,**kwargs): print(m) #打印该参数 if m==1: #判断该参数 print("start") func(*args,**kwargs) print("end") return warpper return inner @test(m=1) #传入参数 def f(): print("2018-06-04") f()
4. 被装饰的函数有返回值怎么处理
res=func(*args,**kwargs)
return res
在执行该函数的时候 接收函数的返回值,并在其后return
5. 多个装饰器的执行顺序
装饰器函数的执行顺序是分为定义阶段和执行阶段的
装饰器函数在被装饰函数定义好后立即执行
在函数定义阶段:执行顺序是从内而外的
在函数执行阶段:执行顺序由外而内,一层层执行
例子:如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def war1(func): print("war1") def inner(*args, **kwargs): print("======war1 start=====") func(*args, **kwargs) #inner print("======war1 end=====") return inner def war2(func): print("war2") def inner(*args,**kwargs): print("======war2 start=====") func(*args,**kwargs) print("======war2 end=====") return inner @war1 @war2 def f(): print("****self****") f()
6. 装饰类的装饰器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import settings def singleton(cls): #cls=Mysql _instance=cls(settings.HOST,settings.PORT) def wrapper(*args,**kwargs): if args or kwargs: obj=cls(*args,**kwargs) return obj return _instance return wrapper @singleton # Mysql=Singleton(Mysql) class Mysql: def __init__(self,host,port): self.host=host self.port=port obj1=Mysql()
7. 被装饰函数的属性变化
Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from functools import wraps def test(func): #当函数被装饰器装饰时,自身的name以及doc都没有了 #,若想获得原来的值,需要加上了一句 # 装饰器修复技术 @wraps(func) def warpper(*args,**kwargs): print("kaishi") func(*args,**kwargs) print("jieshu") return warpper @test def f(): print("2018-06-04") f() print(f.__doc__) # 如果不加装饰器的修复技术,打出的warpper函数的__doc__ print(f.__name__) # 如果不修复,打出的是warpper