4.02Day12函数 装饰器
生活随笔
收集整理的這篇文章主要介紹了
4.02Day12函数 装饰器
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、nonlocal關(guān)鍵字
作用:將 L 與 E 中的名字統(tǒng)一,L中的名字需要先定義
應(yīng)用場(chǎng)景:在被嵌套函數(shù)中修改函數(shù)外的值
案例:
def outer():
x = 10
print(x) # x = 10
def inner():
nonloacl x
x = 20
print(x) # x = 20
inner()
print(x) # x = 20
二、開放封閉原則
1.不能修改被裝飾對(duì)象(函數(shù))的源代碼(封閉)
2.不能更改被修飾對(duì)象(函數(shù))的調(diào)用方式,且能達(dá)到增加功能的效果(開放)
三、裝飾器
要把被裝飾的函數(shù)作為外層函數(shù)的參數(shù),通過(guò)閉包操作后返回一個(gè)替代版函數(shù)
被裝飾的函數(shù):fn
外層函數(shù):outer(func) outer(fn) => func = fn
替代版函數(shù):return inner : 原功能 + 新功能
def fn():
print('原有功能')
# 裝飾器
def outer(tag): # tag為被裝飾函數(shù)的內(nèi)存地址
def inner():
print(新增功能")
tag() # 將被被裝飾函數(shù)的內(nèi)存地址 傳值給tag ,再形成tag()調(diào)用原函數(shù)
return inner
fn = outer(fn) # outer()為函數(shù)outer的return值,
fn() # fn() == inner() 就是 函數(shù)outer的ruturn值--函數(shù) inner的內(nèi)存地址加上()之后 調(diào)用
四:語(yǔ)法糖 @外層函數(shù)
def outer(f):
def inner():
f() # 通過(guò)參數(shù)傳遞原函數(shù)內(nèi)存地址的方式來(lái)調(diào)用原函數(shù)
print("新增功能1")
return inner
def wrap(f):
def inner():
f() # 通過(guò)參數(shù)傳遞原函數(shù)內(nèi)存地址的方式來(lái)調(diào)用原函數(shù)
print("新增功能2")
return inner
@wrap # 被裝飾的順序決定了新增功能的執(zhí)行順序 ==> fn = wrap(fn): inner
@outer # ==> fn = outer(fn): inner
def fn():
print("原有功能")
五、有參有返的函數(shù)被裝飾
def check_usr(fn): # fn, login, inner:不同狀態(tài)下的login,所以參數(shù)是統(tǒng)一的
def inner(usr, pwd):
if not (len(usr) >= 3 and usr.isalpha()): # 在原功能上添加新功能
print('賬號(hào)驗(yàn)證失敗')
return False
result = fn(usr, pwd) # 原有功能
# 也可以在原功能下添加新功能
return result
return inner
@check_usr # 語(yǔ)法糖
def login(usr, pwd):
if usr == 'abc' and pwd =='123qwe':
print('登錄成功')
return True
print('登錄失敗')
return False
# 總結(jié):
# 1.login有參數(shù),所以inner與fn都有相同參數(shù)
# 2.login有返回值,所以inner與fn都有返回值
# 在內(nèi)層函數(shù)中取出原函數(shù)的返回值
inner(usr, pwd):
res = fn(usr, pwd) # 原login的返回值
return res
login = check_usr(login) = inner # 三個(gè)內(nèi)存地址最終都是指向原函數(shù)的
res = login('abc', '123qwe') # inner的返回值
六、裝飾器最終寫法
def wrap(fn): # 最外層中的參數(shù)都是為了傳值給內(nèi)存函數(shù)來(lái)調(diào)用原函數(shù)的
def inner(*args, **kwargs): # 給原函數(shù)傳參
print('前增功能')
result = fn(*args, **kwargs) #接受實(shí)參
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()
八、登錄認(rèn)證功能
is_login = False # 登錄狀態(tài)
def login():
usr = input('usr: ')
if not (len(usr) >= 3 and usr.isalpha()):
print('賬號(hào)驗(yàn)證失敗')
return False
pwd = input('pwd: ')
if usr == 'abc' and pwd =='123qwe':
print('登錄成功')
is_login = True
else:
print('登錄失敗')
is_login = False
# 完成一個(gè)登錄狀態(tài)校驗(yàn)的裝飾器
def check_login(fn):
def inner(*args, **kwargs):
# 查看個(gè)人主頁(yè)或銷售功能前:如果沒有登錄先登錄,反之可以進(jìn)入其功能
if is_login != True:
print('你未登錄')
login()
# 查看個(gè)人主頁(yè)或銷售
result = fn(*args, **kwargs)
return result
return inner
# 查看個(gè)人主頁(yè)功能
@check_login
def home():
print('個(gè)人主頁(yè)')
# 銷售功能
@check_login
def sell():
print('可以銷售')
home()
作用:將 L 與 E 中的名字統(tǒng)一,L中的名字需要先定義
應(yīng)用場(chǎng)景:在被嵌套函數(shù)中修改函數(shù)外的值
案例:
def outer():
x = 10
print(x) # x = 10
def inner():
nonloacl x
x = 20
print(x) # x = 20
inner()
print(x) # x = 20
二、開放封閉原則
1.不能修改被裝飾對(duì)象(函數(shù))的源代碼(封閉)
2.不能更改被修飾對(duì)象(函數(shù))的調(diào)用方式,且能達(dá)到增加功能的效果(開放)
三、裝飾器
要把被裝飾的函數(shù)作為外層函數(shù)的參數(shù),通過(guò)閉包操作后返回一個(gè)替代版函數(shù)
被裝飾的函數(shù):fn
外層函數(shù):outer(func) outer(fn) => func = fn
替代版函數(shù):return inner : 原功能 + 新功能
def fn():
print('原有功能')
# 裝飾器
def outer(tag): # tag為被裝飾函數(shù)的內(nèi)存地址
def inner():
print(新增功能")
tag() # 將被被裝飾函數(shù)的內(nèi)存地址 傳值給tag ,再形成tag()調(diào)用原函數(shù)
return inner
fn = outer(fn) # outer()為函數(shù)outer的return值,
fn() # fn() == inner() 就是 函數(shù)outer的ruturn值--函數(shù) inner的內(nèi)存地址加上()之后 調(diào)用
四:語(yǔ)法糖 @外層函數(shù)
def outer(f):
def inner():
f() # 通過(guò)參數(shù)傳遞原函數(shù)內(nèi)存地址的方式來(lái)調(diào)用原函數(shù)
print("新增功能1")
return inner
def wrap(f):
def inner():
f() # 通過(guò)參數(shù)傳遞原函數(shù)內(nèi)存地址的方式來(lái)調(diào)用原函數(shù)
print("新增功能2")
return inner
@wrap # 被裝飾的順序決定了新增功能的執(zhí)行順序 ==> fn = wrap(fn): inner
@outer # ==> fn = outer(fn): inner
def fn():
print("原有功能")
五、有參有返的函數(shù)被裝飾
def check_usr(fn): # fn, login, inner:不同狀態(tài)下的login,所以參數(shù)是統(tǒng)一的
def inner(usr, pwd):
if not (len(usr) >= 3 and usr.isalpha()): # 在原功能上添加新功能
print('賬號(hào)驗(yàn)證失敗')
return False
result = fn(usr, pwd) # 原有功能
# 也可以在原功能下添加新功能
return result
return inner
@check_usr # 語(yǔ)法糖
def login(usr, pwd):
if usr == 'abc' and pwd =='123qwe':
print('登錄成功')
return True
print('登錄失敗')
return False
# 總結(jié):
# 1.login有參數(shù),所以inner與fn都有相同參數(shù)
# 2.login有返回值,所以inner與fn都有返回值
# 在內(nèi)層函數(shù)中取出原函數(shù)的返回值
inner(usr, pwd):
res = fn(usr, pwd) # 原login的返回值
return res
login = check_usr(login) = inner # 三個(gè)內(nèi)存地址最終都是指向原函數(shù)的
res = login('abc', '123qwe') # inner的返回值
六、裝飾器最終寫法
def wrap(fn): # 最外層中的參數(shù)都是為了傳值給內(nèi)存函數(shù)來(lái)調(diào)用原函數(shù)的
def inner(*args, **kwargs): # 給原函數(shù)傳參
print('前增功能')
result = fn(*args, **kwargs) #接受實(shí)參
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()
八、登錄認(rèn)證功能
is_login = False # 登錄狀態(tài)
def login():
usr = input('usr: ')
if not (len(usr) >= 3 and usr.isalpha()):
print('賬號(hào)驗(yàn)證失敗')
return False
pwd = input('pwd: ')
if usr == 'abc' and pwd =='123qwe':
print('登錄成功')
is_login = True
else:
print('登錄失敗')
is_login = False
# 完成一個(gè)登錄狀態(tài)校驗(yàn)的裝飾器
def check_login(fn):
def inner(*args, **kwargs):
# 查看個(gè)人主頁(yè)或銷售功能前:如果沒有登錄先登錄,反之可以進(jìn)入其功能
if is_login != True:
print('你未登錄')
login()
# 查看個(gè)人主頁(yè)或銷售
result = fn(*args, **kwargs)
return result
return inner
# 查看個(gè)人主頁(yè)功能
@check_login
def home():
print('個(gè)人主頁(yè)')
# 銷售功能
@check_login
def sell():
print('可以銷售')
home()
轉(zhuǎn)載于:https://www.cnblogs.com/shuchengyi/articles/10642942.html
總結(jié)
以上是生活随笔為你收集整理的4.02Day12函数 装饰器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java反序列化漏洞实战
- 下一篇: 当编程语言掌握在企业手中,是生机还是危机