python 装饰器
1、解释器入门
写代码要遵循开放封闭原则,那么什么是开放封闭原则呢,简单的说就是:已经实现的功能代码块不允许被修改,但可以被扩展。即:
开放:对扩展开发;封闭:已经实现的代码块
那么问题来了如何在不更改原有代码前提下实现性能的添加,装饰器就是一个很好的用法
例如:我需要在“登录系统前添加验证功能”,在不更改现有的代码该如何实现?
def test(name): print("登录系统___%s" % name) test("张三")
1)方法1:也许有人会想到使用闭包实现,如
def outer(func): def inner(name): print("验证——————————") func(name) return inner def test(name): print("登录系统___%s" % name) test = outer(test) test("张三") #输出结果 验证—————————— 登录系统___张三
那么问题来了,这样的话在每个文件不同作用域里调用test功能之前都需要添加第12行: test = outer(test),那如果这样的需要添加位置较多的话也不现实,且比较难于查找,出现缺漏的结果也可以自行想象。这里就可以使用方法2
2)方法2:使用装饰器
1 def outer(func): 2 def inner(name): 3 print("验证——————————") 4 func(name) 5 return inner 6 7 8 @outer 9 def test(name): 10 print("登录系统___%s" % name) 11 12 13 test("张三") 14 15 #输出结果 16 验证—————————— 17 登录系统___张三
这里可以看到只需要在test函数前加上 @outer 就可以实现,也可以这么理解 @outer --> test = outer(test)
当装饰的函数有参数时装饰器内部也必须要定义形参,即 第 2 行,在第 4 行时也必须传递参数进行调用
多个函数使用同样的验证功能时也是如此
1 def outer(func): 2 def inner(name): 3 print("验证——————————") 4 func(name) 5 return inner 6 7 8 @outer 9 def test1(name): 10 print("登录系统___%s" % name) 11 12 13 @outer 14 def test2(name): 15 print("查询余额___%s" % name) 16 17 18 test1("张三") 19 test2("李四") 20 21 #输出结果 22 验证—————————— 23 登录系统___张三 24 验证—————————— 25 查询余额___李四
2、多个装饰器
1 def outer1(func): 2 print("_____装饰器outer1____") 3 def inner1(): 4 print("———inner1———————") 5 func() 6 return inner1 7 8 def outer2(func): 9 print("_____装饰器outer2____") 10 def inner2(): 11 print("———inner2———————") 12 func() 13 return inner2 14 15 @outer1 16 @outer2 17 def test(): 18 pass 19 20 test() 21 22 #输出结果 23 _____装饰器outer2____ 24 _____装饰器outer1____ 25 ———inner1——————— 26 ———inner2———————
从结果也可以看到,当有多个装饰器时,装饰器是从内往外装饰,即:1)@outer2--> test = outer2(test) 2) @outer1--> test = outer1(test)
执行到,15,16开始装饰时就会有输出输出23,24行,原因请看上边1)2),在装饰时也会执行outer2(),outer1()两个函数,所以会有输出结果
3、装饰器带返回值
1 def outer(func): 2 def inner(a, b): 3 ret = func(a, b) 4 return ret 5 return inner 6 7 @outer 8 def test(a, b): 9 return a + b 10 11 ret = test(5, 2) 12 print("-----%d" % ret) 13 14 #输出结果 15 -----7
当装饰的函数有返回值时需要将返回值返回,如第 3,4 行
4、通用装饰器
1 def outer(func): 2 def inner(*args, **kwargs): 3 ret = func(*args, **kwargs) 4 return ret 5 return inner 6 7 @outer 8 def test1(a): 9 return a ** 2 10 11 @outer 12 def test2(a, b, c): 13 return a * b * c 14 15 print(test1(3)) 16 print(test2(2, 3, c=5)) 17 18 #输出结果 19 9 20 30
当多个函数都是用同一个装饰器的时候,参数不一致的问题,就的使用通用装饰器来解决,通用即所有的函数都适用的意思。
如上所示,test1与test2函数的参数不一致,也可以用同样的装饰器装饰,第2,3行解决
5、带参数的装饰器
1 def f1(flag=1): 2 def outer(func): 3 def inner(*args, **kwargs): 4 if (flag == 2): 5 print("______%d" % flag) 6 ret = func(*args, **kwargs) 7 else: 8 print("______%d" % flag) 9 ret = func(*args, **kwargs) 10 return ret 11 return inner 12 return outer 13 14 @f1(2) 15 def test(a): 16 return a ** 2 17 18 print(test(3)) 19 20 #输出结果 21 ______2 22 9
当当需要通过不同参数判断装饰器该实现的不同结果时,带参数的装饰器就出现了,如上所示,在装饰器最外层在嵌套一个函数用与接收参数,通过第 4 行判断参数选择相应的功能
下面说说 14行 的执行流程 1)@f1(2) --> f1(2) 执行 f1函数并传值 2 ; 2)f1 函数返回 outer --->@outer;3)@outer --> test = outer(test)
以上就是我对装饰器的一些个人理解了