〖Python〗-- 装饰器
【装饰器】
一、什么是装饰器
器即函数
装饰即修饰,意指为其他函数添加新功能
装饰器定义:本质就是函数,功能是为其他函数添加新功能 #装饰器本身就是函数,被装饰的也是函数。
为什么要用装饰器:
及开放封闭原则。
代码上线后,就是为了尽量避免修改,不修改原函数的源代码和调用方式,并添加新的功能。 # 函数及定义和使用。
装饰器语法:
在被装饰上的正上方写一个@,它会把@这一行下面这一行的函数传递到函数里,再重新赋值给index。
func就是index函数,print(func)返回得是index内存地址。
无参装饰器:
(1):
1
2
3
|
输出: welcome to oldboy run time is 3.000171661376953 |
执行过程:
# 函数应该先定义后使用。 import time def timmer(func): # 定义函数就相当于定义变量名,就相当于把函数的代码绑定到一个名字上面了。 #1,定义变量名 #3 func值就是index def wrapper(): #4 开始执行timmer里面的代码,只要碰到def就跟定义变量名一样,它里边定义的代码全不用管,只要不执行就不用管它。#7 start_time=time.time() #8 # print(func) func() #9 func就是最原始的index stop_time=time.time() #14 print('run time is %s' %(stop_time-start_time)) #15 return wrapper #5 return wrapper 就是return wrapper的内存地址 # index=timmer(index) @timmer #2 timmer要运行timmer(index),所以要跳回去 #10 def index(): #11 time.sleep(3) #12 print('welcome to oldboy') #13 index() #6 index就是wrapper函数,wrapper是一个闭包函数,里边包含了一个状态,就是func。
(2): # 第一次是home,第二次是home("name")
1
2
3
4
5
6
7
|
输出: welcome to dragon home page run time is 2.0001144409179688 egon 123 run time is 0.0 - - - - - - - - - - - - run time is 0.0 |
注意:传参数,需要加上*args,**kwargs
(3):
1
2
3
4
|
输出: my_max function run time is 0.0 - - - - - - - - 2 |
注意:如果原函数需要有返回值,则装饰器也需要设置return res。完整正确的无参装饰器写法就是以上写法。
有参装饰器:
(1): #第一步是函数()的效果,第二步是@auth的效果
1
|
输出:还他妈的不会玩 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#有参函数执行流程 def auth2(auth_type): #1 #3 def auth(func): #4 #6 def wrapper( * args, * * kwargs): #7 #10 if auth_type = = 'file' : #11 name = input ( 'username: ' ) password = input ( 'password: ' ) if name = = 'zhejiangF4' and password = = 'sb945' : print ( 'auth successfull' ) res = func( * args, * * kwargs) return res else : print ( 'auth error' ) elif auth_type = = 'sql' : #12 print ( '还他妈不会玩' ) #13 return wrapper #8 return auth #5 @auth2 (auth_type = 'sql' ) #2 def index(): print ( 'welcome to inex page' ) # @auth # def home(): # print('welcome to home page') index() #9 |
多个装饰器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#多个无参装饰器: # @aaa # def func(): # pass # # func=aaa(func) # @ccc # @bbb # @aaa # def func(): # pass # # func=ccc(bbb(aaa(func))) #多个有参装饰器 # @ccc('c') # @bbb('b') # @aaa('a') # def func(): # pass # # func=ccc('c')(bbb('b')(aaa('a')(func))) |
多个装饰器应用:
import time current_login={'name':None,'login':False} def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) #my_max(1,2) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper def auth2(auth_type='file'): def auth(func): # print(auth_type) def wrapper(*args,**kwargs): if current_login['name'] and current_login['login']: res=func(*args,**kwargs) return res if auth_type == 'file': name=input('username: ') password=input('password: ') if name == 'luchuan' and password == '123': print('auth successfull') res=func(*args,**kwargs) current_login['name']=name current_login['login']=True return res else: print('auth error') elif auth_type == 'sql': print('还他妈不会玩') return wrapper return auth @timmer @auth2(auth_type='file') #@auth #index=auth(index) def index(): print('welcome to inex page') @auth2() def home(): print('welcome to home page') #调用阶段 index() home()
装饰器帮助信息补充:
import time from functools import wraps def timmer(func): @wraps(func) def wrapper(*args,**kwargs): 'sssssssssssss' # 不加wraps,就会返回'sssssss'帮助信息 start_time=time.time() func(*args,**kwargs) #home(name) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return wrapper @timmer def func(x): 'func test' print(x) func(1) print(func.__doc__) # 查看帮助信息的两种方式 # print(help(func)) #不加wraps,输出sssssssss #加上wraps,则输出:from test
二、装饰器需要遵循的原则
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
三、实现装饰器知识储备
装饰器=高阶函数+函数嵌套+闭包
装饰器:一个外部函数、一个内部函数、一个return 、如果是有参装饰器,外部再包一层函数。
四、高阶函数
高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
def foo(): print('我的函数名作为参数传给高阶函数') def gao_jie1(func): print('我就是高阶函数1,我接收的参数名是%s' %func) func() def gao_jie2(func): print('我就是高阶函数2,我的返回值是%s' %func) return func gao_jie1(foo) gao_jie2(foo)
#高阶函数应用1:把函数当做参数传给高阶函数 import time def foo(): print('from the foo') def timmer(func): start_time=time.time() func() stop_time=time.time() print('函数%s 运行时间是%s' %(func,stop_time-start_time)) timmer(foo) #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名 import time def foo(): print('from the foo') def timmer(func): start_time=time.time() return func stop_time=time.time() print('函数%s 运行时间是%s' %(func,stop_time-start_time)) foo=timmer(foo) foo() #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
高阶函数总结
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
五、函数嵌套
def father(name): print('from father %s' %name) def son(): print('from son') def grandson(): print('from grandson') grandson() son() father('林海峰')
六、闭包
''' 闭包:在一个作用域里放入定义变量,相当于打了一个包 ''' def father(name): def son(): # name='alex' print('我爸爸是 [%s]' %name) def grandson(): # name='wupeiqi' print('我爷爷是 [%s]' %name) grandson() son() father('林海峰')
七、无参装饰器
无参装饰器=高级函数+函数嵌套
基本框架
1 #这就是一个实现一个装饰器最基本的架子 2 def timer(func): 3 def wrapper(): 4 func() 5 return wrapper
加上参数
1 def timer(func): 2 def wrapper(*args,**kwargs): 3 func(*args,**kwargs) 4 return wrapper
加上功能
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 func(*args,**kwargs) 6 stop_time=time.time() 7 print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) 8 return wrapper
加上返回值
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 res=func(*args,**kwargs) 6 stop_time=time.time() 7 print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time)) 8 return res 9 return wrapper
使用装饰器
1 def cal(array): 2 res=0 3 for i in array: 4 res+=i 5 return res 6 7 cal=timer(cal) 8 cal(range(10))
语法糖@
1 @timer #@timer就等同于cal=timer(cal) 2 def cal(array): 3 res=0 4 for i in array: 5 res+=i 6 return res 7 8 cal(range(10))
八、装饰器应用示例
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, {'name':'病毒尖er','passwd':'123'}, ] current_user={'username':None,'login':False} def auth_func(func): # 用户登陆验证 def bar(*args,**kwargs): if current_user["username"] and current_user["login"]: res = func(*args,**kwargs) return res for i in range(3): username = input("请输入用户名:").strip() passwd = input("请输入密码:").strip() for item in user_list: if username == item["name"] and passwd == item["passwd"]: current_user["username"] = username current_user["login"] = True res=func(*args,**kwargs) return res else: print("您输入的用户名或者密码有误") return bar @auth_func # 相当于index=auth_func(index) def index(): print("欢迎来到京东商城" ) @auth_func # 相当于home=auth_func(home) def home(name): print("%s欢迎回家" %name) @auth_func # 相当于shop_car=auth_func() def shop_car(name): print("%s的购物车是空的,赶紧购物咯" %name) index() home(current_user["username"]) shop_car(current_user["username"])
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, {'name':'病毒尖er','passwd':'123'}, ] current_user={'username':None,'login':False} def auth(auth_type="file"): def auth_func(func): # 用户登陆验证 def bar(*args,**kwargs): if auth_type == "file": if current_user["username"] and current_user["login"]: res = func(*args,**kwargs) return res for i in range(3): # 给用户三次重复输入的机会 防止进入其它功能进入下一层 username = input("请输入用户名:").strip() passwd = input("请输入密码:").strip() for item in user_list: if username == item["name"] and passwd == item["passwd"]: current_user["username"] = username current_user["login"] = True res=func(*args,**kwargs) return res else: print("您输入的用户名或者密码有误") elif auth_type == "ldap": print("快点告诉你,你用我画的蜡笔") res = func(*args,**kwargs) return res return bar return auth_func @auth(auth_type="file") def index(): print("欢迎来到京东商城" ) @auth(auth_type="ldap") # 传参数 类型对应 def home(name): print("%s欢迎回家" %name) @auth(auth_type="file") def shop_car(name): print("%s的购物车是空的,赶紧购物咯" %name) index() home(current_user["username"]) shop_car(current_user["username"])
年轻时不多经历一点,老了拿什么下酒.