装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> func1 = timer(func1) def func1(): print('in func1') func1()
完整的装饰,万能的装饰
def timmer(qqxing): #timmer是装饰器的名字,传入的参数就是被装饰的函数 def inner(*args,**kwargs): #在装饰器中需要定义一个内部函数 print('调用func之前') ret = qqxing(*args,**kwargs) #被装饰的函数,并且要执行 print('调用func之后') return ret return inner #将内部函数的名字返回 @timmer #语法糖 func = timmer(func) def func(name): print('%s的公司好老板好同事好'%(name)) return 1111111111 ret = func('俊杰') print('result : %s'%ret) 输出: 调用func之前 俊杰的公司好老板好同事好 调用func之后 result : 1111111111
装饰器的固定结构:
#装饰器的固定结构 def wrapper(func): def inner(*args,**kwargs): """被装饰函数执行之前要添加的代码""" ret = func(*args,**kwargs) """被装饰函数执行之后要添加的代码""" return ret return inner
多个装饰器装饰同一个函数
有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f()
开放封闭原则
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
练习:
#用装饰器实现,访问art或者dar函数,登陆一次之后,无需再次登录
# art()
# dar()
flag = False def login(func): def inner(*args,**kwargs): global flag if flag == False: username = input('用户名:') password = input('密码:') if username == 'alex' and password == 'somebody': print('登录成功') flag = True if flag == True: ret = func(*args,**kwargs) return ret return inner @login def art(): print('欢迎来到文章页') @login def dar(): print('欢迎来到日记页') dar() art() 输出: 用户名:alex 密码:somebody 登录成功 欢迎来到日记页 欢迎来到文章页
实现日志功能:
def log(func): def inner(*args,**kwargs): print('你要调用%s函数了'%func.__name__) ret = func(*args,**kwargs) return ret return inner @log #f1 = log(f1) def f1(): print('f1') @log def f2(): print('f2') #日志 f1() f2() 输出: 你要调用f1函数了 f1 你要调用f2函数了 f2
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' print(func2(2)) # 'fun2 over' 输出: in func2 and get a:2 0.0009996891021728516 fun2 over
装饰器进阶:
进阶一:
def outer(flag): def wrapper(func): def inner(*args,**kwargs): if flag: print('执行%s之前我加了一个功能'%func.__name__) ret = func(*args,**kwargs) #qqxing return ret return inner return wrapper @outer(True) #qqxing = wrapper(qqxing) def qqxing(): print('qqxing') @outer(False) #wahaha = wrapper(wahaha) def wahaha(): print('wahaha') qqxing() wahaha() #2000 #1000 #1000 # def outer(flag,flag2): # def wrapper(func): # def inner(*args,**kwargs): # ret = func(*args,**kwargs) # return ret # return inner # return wrapper # # @outer(True,False) #带参数的装饰器 ==》@wrapper ==》func = wrapper(func) ==> func == inner # def func():pass
进阶二:
def wrapper2(func): #inner1 def inner2(*args,**kwargs): print('in wrapper 2,before') ret = func(*args,**kwargs) #inner1 print('in wrapper 2,after') return ret return inner2 def wrapper1(func): #qqxing def inner1(*args,**kwargs): print('in wrapper 1,before') ret = func(*args,**kwargs) #qqxing print('in wrapper 1,after') return ret return inner1 @wrapper1 #qqxing = inner1 @wrapper2 #qqxing = wrapper2(inner1) = inner2 def qqxing(): print('qqxing') qqxing() #inner2 #login 一个实现login的装饰器 #timmer 一个计算函数时间的装饰器 #先登录,再计算时间