1. 程式人生 > >閉包函數,裝飾器

閉包函數,裝飾器

更改 變調 out 裝飾器 loaded ring args pro 主頁

nonlocal關鍵字

# 作用:將 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()

 

閉包函數,裝飾器