DAY12 装饰器

一.nonlocal关键字

​ 1.作用:将 L 与 E(E中的名字需要提前定义)的名字统一

​ 2.应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值

​ 3.案例:

​ def outer()

​ num = 10

​ print(num) # 10
​ def inner():
​ nonlocal num
​ num = 20
​ p77rint(num) # 20
​ inner()
​ print(num) # 20

二.开放封闭原则

​ 1.定义:不改变调用方式与源代码前提下增加功能

​ 2.要求:

​ 1.不能修改被装饰对象(函数)的源代码(封闭)

​ 2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)

三.装饰器

​ 定义:把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数

​ def fn():

​ print("原有功能")

​ 装饰器:

​ def outer(func):

​ def inner():

​ func() # 原有的功能fn()

​ print('新增功能')

​ return inner # 拓展功能后的fn

​ fn = outer(fn) # 将拓展功能后的功能函数重新赋值给fn

​ fn()

​ 1.被装饰的函数:fn

​ 2.外层函数:outer(func) outer(fn) ==> func = fn

​ 3.替代版函数:return inner :原功能+新功能

四.@语法糖

​ python中装饰器 fn = outer(fn)可以中@outer来代替其中@后跟的是外层函数

​ def outer(func):

​ def inner():

​ func() # 原有的功能fn()

​ print('新增功能')

​ return inner # 拓展功能后的fn

​ def warp(func):

​ def inner():

​ func() # 原有的功能fn()

​ print('新增功能')

​ return inner # 拓展功能后的fn

​ @warp # 被装饰的顺序决定了新增功能的执行顺序

​ @outer # <==> fn = outer(fn) : inner

​ def fn():

​ print("原有功能")

五.有参数有返回值的函数被装饰

​ def check_usr(fn): # fn, login, inner:不同状态下的login,所以参数是统一的
​ def inner(usr, pwd):

​ #在原功能上添加新功能

​ if not (len(usr) >= 3 and usr.isalpha()):
​ print('账号验证失败')
​ return False
​ #原有功能
​ result = fn(usr, pwd)
​ #在原功能下添加新功能
...
​ return result

return inner

​ @check_usr
​ def login(usr, pwd):
​ if usr == 'abc' and pwd =='123qwe':
​ print('登录成功')
​ return True
​ print('登录失败')
​ return False

​ 总结:

​ 1.login有参数,所以inner与fn都有相同参数

​ 2.login有返回值,所以inner与fn都有返回值

六.装饰器最终

​ def wrap(fn):
​ def inner(*args, **kwargs):
​ print('前增功能')
​ result = fn(*args, **kwargs)
​ print('后增功能')
​ return result
​ return inner



​ @wrap
​ def fn1():
​ print('fn1的原有功能')
​ @wrap
​ def fn2(a, b):
​ print('fn2的原有功能')
​ @wrap
​ def fn3():
​ print('fn3的原有功能')
​ return True
​ @wrap
​ def fn4(a, *, x):
​ print('fn4的原有功能')
​ return True

​ fn1()
​ fn2(10, 20)
​ fn3()
​ fn4(10, x=20)

七.带参数的装饰器

​ def outer(input_color):
​ def wrap(fn):
​ if input_color == 'red':
​ info = '\033[36;41mnew action\33[0m'
​ else:
​ info = 'yellow:new action'

​ def inner(*args, **kwargs):
​ pass
​ result = fn(*args, **kwargs)
​ print(info)
​ return result
​ return inner
​ return wrap # outer(color) => wrap

​ color = input('color: ')
​ @outer(color) # @outer(color) ==> @wrap # func => inner
​ def func():
​ print('func run')

​ func()
posted @ 2019-04-02 15:28  Lip&amp;Hip  阅读(81)  评论(0编辑  收藏  举报