装饰器
2019-07-29 17:34 风e逸 阅读(75) 评论(0) 收藏 举报装饰器定义:
在不改变源程序代码和运行方式的前提下,为程序添加附加功能的函数。
装饰器的两大原则:
1.不修改被装饰函数的源代码
2.不修改被装饰函数的运行方式
装饰器的知识储备:
装饰器 = 高阶函数 + 函数嵌套 + 闭包
a) 高阶函数:
定义: 一个函数的参数是一个函数,或者返回值是一个函数,两者满足其一,这个函数就叫高阶函数。

1 import time 2 def foo(): 3 print('这是一个函数') 4 time.sleep(0.3) 5 return 0 6 def test(func): # 用这个函数来测试foo函数的运行时间 7 start_time = time.time() 8 func() 9 stop_time = time.time() 10 print('函数[%s]的运行时间为%s' %(func, (stop_time-start_time))) 11 return func 12 res = test(foo)
b) 函数嵌套:
定义:定义一个函数,函数的内部定义了另一个函数,这种情况叫做函数的嵌套。

1 def taowa(num, name_1, name_2): 2 print('您选择的是%s 层套娃' % num) 3 print('外层套娃颜色是 %s' % name_1) 4 5 def taowa_sec(num_c): 6 print('第%s 层套娃的颜色是%s' %(num_c + 2, name_2)) 7 8 if num > 1: 9 for i in range(num - 1): 10 taowa_sec(i) 11 return 0 12 13 taowa(2, '红', '绿') 14 15 输出结果: 16 您选择的是2 层套娃 17 外层套娃颜色是 红 18 第2 层套娃的颜色是绿
装饰器的框架:
1 def timer(func): 2 def test(): 3 # print(func) 4 start_time = time.time() 5 func() 6 stop_time = time.time() 7 print('运行时间是%s' % (stop_time-start_time)) 8 return test 9 def foo(): 10 time.sleep(0.3) 11 print('我是一个函数') 12 return 0 13 foo = timer(foo) # foo储存的为test的地址 14 foo()
# 装饰器其实是一种偷换概念的存在,对于用户来说,运行的方法和名称没变,在上面例子中,函数名为foo,运行方法为foo()。但对于程序来说,实际上foo对应的函数地址已经改变,此时调用foo()运行的是一个包含了原函数+附加功能的新的函数,即 test()。
python为了简化操作:提供了@ + 装饰器名的语法,来替代
foo = timer(foo) # foo储存的为test的地址
这一步的操作。
刚刚说过,由于偷换概念,因此执行foo()实际运行的是test(),那么对于函数来说,返回值已经由原来foo()得返回值改变为test()的返回值,为了同步返回值,
需要在装饰器函数中加上一步返回值操作。同时需要获取并为test()加上原函数的参数。
因此装饰器实际操作为:
import time # 定义一个装饰器函数 def timer(func): def test(*args,**kwargs): # 拿到原函数的参数 # print(func) start_time = time.time() res=func(*args,**kwargs) # 获取返回值,并传入参数 stop_time = time.time() print('运行时间是%s' % (stop_time-start_time)) return res #同步返回值 return test @ timer def foo(): # 这个作为原函数 time.sleep(0.3) print('我是一个函数') return 0 re=foo() print(re)
装饰器的验证功能:
装饰器函数可以为函数提供验证功能,可用于网站的登录验证。

1 def yanzheng(func): 2 def wrapp(*args, **kwargs): 3 username = input('username:') 4 passwd = input('password:') 5 if username == 'xtzz' and passwd == 'abc': 6 res = func(*args, **kwargs) 7 return res 8 else: 9 print('用户名或密码错误') 10 return wrapp 11 12 # 在下列函数中,应用装饰器提供验证功能 13 # 用户名:xtzz 密码:abc 14 def welcome(): 15 print('欢迎') 16 17 @yanzheng 18 def home(name): 19 print('%s 欢迎回家' %name) 20 21 @yanzheng 22 def shopping_car(name): 23 print('%s 的购物车里有%s, %s, %s' %(name, 'aaa', 'bbb', 'ccc')) 24 25 # 运行程序: 26 welcome() 27 home('xtzz') 28 shopping_car('xtzz')