# 做用:將 L 與 E(E中的名字須要提早定義) 的名字統一 # 應用場景:若是想在被嵌套的函數中修改外部函數變量(名字)的值 # 案例: def outer(): num = 10 print(num) # 10 def inner(): nonlocal num num = 20 p77rint(num) # 20 inner() print(num) # 20
''' 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 inner def 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 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都有返回值 """ inner(usr, pwd): res = fn(usr, pwd) # 原login的返回值 return res login = check_usr(login) = inner res = login('abc', '123qwe') # inner的返回值 """
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()
is_login = False # 登陸狀態 def login(): usr = input('usr: ') if not (len(usr) >= 3 and usr.isalpha()): print('帳號驗證失敗') return False pwd = input('pwd: ') if usr == 'abc' and pwd =='123qwe': print('登陸成功') is_login = True else: print('登陸失敗') is_login = False # 完成一個登陸狀態校驗的裝飾器 def check_login(fn): def inner(*args, **kwargs): # 查看我的主頁或銷售功能前:若是沒有登陸先登陸,反之能夠進入其功能 if is_login != True: print('你未登陸') login() # 查看我的主頁或銷售 result = fn(*args, **kwargs) return result return inner # 查看我的主頁功能 @check_login def home(): print('我的主頁') # 銷售功能 @check_login def sell(): print('能夠銷售') home()