1、装饰器的本质是函数,主要用来装饰其他函数,也就是为其他函数添加附加功能
2、装饰器的原则:
(1) 装饰器不能修改被装饰的函数的源代码
(2) 装饰器不能修改被装饰的函数的调用方式
3、实现装饰器的知识储备
(1) Python中函数即‘变量’
a、变量在Python中的存储
1 x='Tomwenxing' 2 y=x
[说明]:
当Python解释器遇到语句x='Tomwenxing'时,它主要完成了两样工作:
1.在内存中开辟了一片空间用来存储字符串‘Tomwenxing’
2.在内存从创建了一个名为x的变量,并用它指向字符串‘Tomwenxing’所占据的内存空间(可以理解为房间和房间号的关系)
而语句y=x意为将变量x对字符串的引用赋值给变量y,即在内存中创建一个变量y,并使其指向变量x所指向的内存空间
b、函数在Python中的存储
1 def test(): 2 pass
[说明]:
在Python中,函数的存储和变量相似,以上面的函数为例,Python解释其主要做两件事:
1.在内存中开辟一个内存空间,用来存储函数代码的字符串(本例中代码只有一句:pass)
2.在内存中创建一个变量test,用来指向存储函数代码字符串的内存空间(相当于test=‘函数体’)
因此说在Python中函数即变量
(2) 高阶函数(下面两个条件满足任何一个即为高阶函数)
a、把一个函数名当做实参传递给另外一个函数
[对装饰器的影响]:达到“在不修改被装饰函数源代码的情况下为其添加功能”的效果
1 import time 2 def bar(): 3 time.sleep(2) 4 print('in the bar') 5 6 def test(func): 7 start_time=time.time() 8 func() 9 stop_time=time.time() 10 print('函数的运行时间为:',stop_time-start_time) 11 12 test(bar)
b、返回值中包含函数名
[对装饰器的影响]:达到“不改变函数的调用方式“的效果
1 import time 2 def bar(): 3 time.sleep(3) 4 print('in the bar') 5 6 def test2(func): 7 print('新添加的功能') 8 return func 9 10 bar=test2(bar) 11 bar()
(3) 嵌套函数:在一个函数体内用def去声明一个新的函数(不是调用)
1 def foo(): 2 print('in the foo') 3 def bar(): #声明一个新的函数,而不是调用函数 4 print('in the bar') 5 bar() 6 7 foo()
4、装饰器的语法:高阶函数+嵌套函数=》装饰器 (下面的例子可以用pycharm的调试器调试一下,看看代码的运行顺序)
1 import time 2 def timer(func): 3 def deco(*args,**kwargs):#使用了不定参数 4 start_time=time.time() 5 res=func(*args,**kwargs) #运行函数 6 stop_time=time.time() 7 print('运行时间:',stop_time-start_time) 8 return res # 若无返回值,则返回None 9 return deco 10 11 @timer #等价于test1=timer(test1)=deco,即test1()=deco() 12 def test1(): 13 time.sleep(3) 14 print('in the test1') 15 16 @timer #等价于test2=timer(test2)=deco,即test2(name)=deco(name) 17 def test2(name): 18 time.sleep(3) 19 print('in the test2',name) 20 21 test1() 22 print('-------------分界线------------------------') 23 test2('Tomwenxing')
5、带参数的装饰器
1 user,passwd='Tomwenxing','123' 2 #如装饰器带参数,一般是三层嵌套 3 def auth(auth_type): #第一层的参数是装饰器的参数 4 def outer_wrapper(func):#第二层的参数是装饰器要装饰的目标函数 5 def wrapper(*args,**kwargs):#第三次的参数是目标函数的参数 6 if auth_type=='local': 7 username = input('Username:').strip() 8 password = input('Password:').strip() 9 if user == username and passwd == password: 10 print('用户Tomwenxing已经成功登录!') 11 res = func(*args, **kwargs) #运行目标函数 12 return res 13 else: 14 exit('用户名或密码有错误') 15 elif auth_type=='ldap': 16 print('暂不支持这种登录方式!') 17 return wrapper 18 return outer_wrapper 19 20 def index(): 21 print('欢迎来到index页面') 22 23 @auth(auth_type='local') #home=wrapper() 24 def home(name): 25 print('%s,欢迎来到home页面' %name) 26 return 'This is home page' 27 28 @auth(auth_type='ldap') 29 def bbs(): 30 print('欢迎来到bbs页面 ') 31 32 33 index() 34 print('----------------------分界线-------------------') 35 print('函数的返回值为:',home('wenxing')) 36 print('----------------------分界线-------------------') 37 bbs()