1. 程式人生 > >DAY12 裝飾器

DAY12 裝飾器

函數的參數 提前 賬號 重新 abc 開放封閉原則 red strong func

一.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 :原功能+新功能

四[email protected]語法糖

? 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()

DAY12 裝飾器