python基础之装饰器
定义
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
本质就是函数,功能 为其它函数添加附加功能
原则:
- 不修改被修饰函数的源代码
- 不修改被修饰函数的调用方式
装饰器的知识储备
装饰器 = 高阶函数+函数嵌套+闭包
这里面要明确高阶函数的定义
1 import time#导入时间模块儿 2 def foo(func): # func = test 3 def bar(*args,**kwargs): 4 start_time = time.time() 5 res=func(*args,**kwargs) # 这里就是在运行test() 赋予变量 6 stop_time = time.time() 7 print("狼来了的时间为%s" %(stop_time-start_time)) 8 return res # 返回test()的值 9 return bar 10 @foo # @foo 相当于 test=foo(test) 调用foo函数并将test传给func 11 def test(name,age): 12 time.sleep(1) 13 print("名字叫%s年龄为%s的狼来了" %(name,age)) 14 return "村里的羊被吃了" 15 ret = test("灰太狼",age=10) # test()意在运行bar() # 输出res的返回值 16 print(ret)
高阶函数的定义
1、函数接收的参数是一个函数名 2、函数的返回值是一个函数名
以上条件任意满足一条,都可以称之为高阶函数
1 def foo(): 2 print('我的函数名字作为参数传给高阶函数啦') 3 def gao_jie1(func): # 传函数名 func = foo 4 print('我就是高阶函数1号,我接收的参数名是%s' %func) 5 func() # 意在运行 foo()函数 6 7 def gao_jie2(func): # func = foo 8 print('我就是高阶函数2号,我的返回值是%s' %func) 9 return func # 此时func为返回foo的的内存地址 10 11 gao_jie1(foo) 12 print(gao_jie2(foo)) 13 14 输出 15 我就是高阶函数1号,我接收的参数名是<function foo at 0x000001FDF179F598> 16 我的函数名字作为参数传给高阶函数啦 17 我就是高阶函数2号,我的返回值是<function foo at 0x000001FDF179F598> 18 <function foo at 0x000001FDF179F598>
1 import time 2 def foo(): 3 time.sleep(2) 4 print("狼来了") 5 def test(func): # func = foo 6 start_time = time.time() 7 func() # func()意在调用 foo()函数 8 stop_time = time.time() 9 print("狼来的时间为%s" %(stop_time-start_time)) 10 test(foo) # 调用test()函数 并用函数名为参数传进去
总结:1、函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下添加新功能
不足:改变了函数的调用方式
#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名 import time def foo(): time.sleep(2) print("狼来了") def test(func): # func = foo的内存地址 start_time = time.time() return func # 返回值为foo的内存地址 stop_time = time.time() print("狼来的时间为%s" %(stop_time-start_time)) foo = test(foo) # 调用test函数并将函数名foo做为参数传进去 print(foo) # 输出返回值的结果 foo的内存地址 foo() # 运行foo()函数 #没有改变函数foo的调用方式,但是也没有给函数增加新功能
总结:2、函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:没有为函数增加新的功能
函数嵌套
1 def father(name): 2 print('from father %s' %name) 3 def son(): 4 print('from son') 5 def grandson(): 6 print('from grandson') 7 grandson() 8 son() 9 father('舒克') 10 11 输出 12 from father 舒克 13 from son 14 from grandson
闭包
1 ''' 2 闭包:在一个作用域里放入定义变量,相当于打了一个包 3 ''' 4 def father(name): 5 def son(): 6 # name='alex' 7 print('我爸爸是 [%s]' %name) 8 def grandson(): 9 # name='wupeiqi' 10 print('我爷爷是 [%s]' %name) 11 grandson() 12 son() 13 father('舒克')
无参装饰器=高阶函数+嵌套函数
基本框架
# 无参装饰器,这是一个实现装饰器最基本的框架 def timmer(func): def bar(): func() return bar
加入参数之后
# 带参数装饰器 def timmer(func): def bar(*args,**kwargs): func(*args,**kwargs) return bar
加入时间功能
# 加一个时间的小功能 import time def timmer(func): def bar(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print("狼来的时间为%s" %(stop_time-start_time)) return bar
加入函数运行的返回值
# 加入函数返回值 import time def timmer(func): def bar(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print("狼来的时间为%s" %(stop_time-start_time)) return res return bar
使用装饰器
import time def timmer(func): def bar(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print("博尔特跑10米的时间为%s" %(stop_time-start_time)) return res return bar # 使用装饰器 def test(): time.sleep(1) print("到达终点") return "世界飞人" test=timmer(test) print(test()) 输出 到达终点 博尔特跑10米的时间为1.0006155967712402 世界飞人
语法糖@
import time def timmer(func): def bar(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print("博尔特跑10米的时间为%s" %(stop_time-start_time)) return res return bar # 使用装饰器 @timmer # @timmer就相当于 test=timmer(test) def test(): time.sleep(1) print("到达终点") return "世界飞人" # test=timmer(test) print(test()) # test()是在运行bar()函数
应用示例
无参装饰器:
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"])