''' 1.不能修改被装饰对象(函数)的源代码(封闭) 2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放) '''
装饰器
# 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数 # 被装饰的函数:fn # 外层函数:outer(func) outer(fn) => func = fn # 替代版函数: return inner: 原功能+新功能def fn():print("原有功能")# 装饰器 def outer(tag):def inner():tag()print(新增功能")return inner fn = outer(fn) fn()
语法糖@外层函数
def outer(f):def inner():f()print("新增功能1")return innerdef wrap(f):def inner():f()print("新增功能2")return inner @wrap # 被装饰的顺序决定了新增功能的执行顺序 @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 resultreturn inner@check_usr def login(usr, pwd):if usr == 'abc' and pwd =='123qwe':print('登录成功')return Trueprint('登录失败')return False# 总结: # 1.login有参数,所以inner与fn都有相同参数 # 2.login有返回值,所以inner与fn都有返回值""" inner(usr, pwd):res = fn(usr, pwd) # 原login的返回值return reslogin = check_usr(login) = innerres = login('abc', '123qwe') # inner的返回值 """
def wrap(fn):def inner(*args, **kwargs):print('前增功能')result = fn(*args, **kwargs)print('后增功能')return resultreturn 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 Truefn1() fn2(10, 20) fn3() fn4(10, x=20)