装饰器
1、什么是装饰器
- 装饰器本质是函数,用来给其他函数添加新的功能
- 特点:不修改调用方式、不修改源代码
2、装饰器的作用
- 装饰器作用:本质是函数(装饰其他函数)就是为其他函数添加其他功能
- 装饰器必须准寻得原则:
- 不能修改被装饰函数的源代码、不能修改被装饰函数的调用方式
- 实现装饰器知识储备:
- 函数即“变量”
- 高阶函数
- 嵌套函数 高阶函数+潜逃函数=》装饰器
3、使用高阶函数模仿装饰器功能
1.定义:把一个函数名当做实参传给另一个函数
2.返回值中包含函数名
3.下面使用高阶函数虽然可以实现装饰器的一些功能,但是违反了装饰器不能改变调用方式的原则,
以前使用bar()现在将调用方式改编成了test1(bar)就是将bar的函数名当做变量传给了test1()
#! /usr/bin/env python # -*- coding: utf-8 -*- import time def timer(func): start_time = time.time() func() print '函数执行时间为', time.time() - start_time def test(): print '开始执行test' time.sleep(3) print 'test执行结束' timer(test) ''' 开始执行test test执行结束 函数执行时间为 3.00332999229 '''
4.高阶函数——不修改高阶函数的调用方式增加新的功能(但是无法传参数)
注:bar = test2(bar) 等价于:@timer重新将函数名bar赋值,将原函数bar的内存地址当做实参传递该函数test2(),再将test2()赋值给bar
import time def bar(): time.sleep(3) print("in the bar") def test2(func): print(func) return func bar = test2(bar) bar()
5.嵌套函数
嵌套函数:在一个函数中嵌套另一个函数,并在函数内部调用
def foo(): print("in the foo") def bar(): print("in the bar") bar() foo()
4、能够适应90%的业务需求
- 在装饰器中 @timer等价于 test1=timer(test1)
- 在timer()函数中返回值是return deco
- 所以timer(test1)作用是将函数test1内存地址当做参数传递给timer()
- timer() 函数最后将运行后的函数deco内存地址作为返回值返回
- test1=timer(test1)作用就是将将deco函数内存地址赋值给test1,所以最后运行test1()就相当于运行deco()
- 所以最后调用时给test2()传入参数就相当于给deco传入参数
import time def timer(func): #timer(test1) func=test1 def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) #run test1 stop_time = time.time() print("running time is %s"%(stop_time-start_time)) return deco @timer # test1=timer(test1) def test1(): time.sleep(3) print("in the test1") @timer def test2(name): print("in the test2",name) test1() test2("tom")
5、对特定网页进行身份验证
import time user,passwd = 'aaa','123' def auth(func): def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if user == username and password == passwd: print("User has passed authentication") res = func(*args,**kwargs) #这里执行func()相当于执行调用的函数如home() return res #为了获得home()函数返回值,可以将执行结果赋值给res然后返回print(home())结果是"from home"而不是"None"了 else: exit("Invalid username or password") return wrapper def index(): print("welcome to index page") @auth def home(): print("welcome to home page") return "from home" @auth def bbs(): print("welcome to bbs page") index() print(home()) #在这里调用home()相当于调用wrapper() bbs()
6、实现对不同网页不同方式的身份认证
- @auth(auth_type="local")代码作用
- 在上面的代码中使用@auth相当于先将home函数的内存地址当做变量传入auth()函数,执行结果后home()相当于wrapper()
- 而在这里验证的时候犹豫@auth(auth_type="local")中有()括号,那么就相当于将执行auth()函数而且是将auth_type="local当做参数传入到auth()函数执行
- 所以outer_wrapper函数也会执行,outer_wrapper函数的执行结果返回的就是wrapper()函数的内存地址
- 所以最终结果同样是执行home()函数就相当于执行wrapper函数
- 但是有所不同的是着这个版本中我们可以在外层的auth函数中传入新的参数帮组我们根据需求判断
import time user,passwd = 'aaa','123' def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:", *args, **kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("