記憶碎片之python裝飾器及多個裝飾器聯合使用
阿新 • • 發佈:2021-01-18
技術標籤:經驗分享python裝飾器裝飾器進階裝飾器心得裝飾器用法
import functools
def outer(func):
functools.wraps(func) # inner.__name__ = func.__name__ inner.__doc__ = func.__doc__ 偽裝的更像主函式而已
def inner(*args, **kwargs): # 如果func()有引數,那裝飾器之後func就等價於inner函式,所以也需要引數接收
print("原函式執行前的任務") # 當然也可以直接形象接受引數,前提是你知道原函式的引數,如inner(a,b=1,*args, **kwargs)
if False:
res = func(*args, **kwargs) # 這裡是真正呼叫原函式,原函式如果有引數,這裡肯定也得有引數啊,這裡的引數從inner引數獲取
return res
else:
print("原函式執行後的任務")
print("反向解析跳轉登陸介面")
return inner
@outer
def func(a, b=1):
print("進入個人詳情頁" )
# func("a", 2)
# 裝飾器說明:
# 對於裝飾器有一點必須要說明,不然很難理解,就是函式名是否加括號的問題
# 函式加括號表示對函式的呼叫
# 函式不加括號表示引用,可以理解成一個變數,指向函式程式碼所在的地址
# 如果上面兩行不明白的,會直接在下面兩句中迷茫,這也是我原來學裝飾器迷茫的地方,(迷茫:一個func被賦值,然後func()就裝飾器或閉包生效了)
# func新增裝飾器之後 相當於是func = outer(func) 此時函式func相當於一個變數,指向outer(func)函式
# 然而 outer(func) return返回的是inner函式 return 後面的函式是不加括號的,表示引用inner函式
# 所以在執行 func函式的時候,實際上執行的是inner函式 inner函式返回原函式的值,所以在拿該值的時候會執行原來的func函式
# 在inner函式中對原函式func做了功能擴充套件 比如做是否登陸的判斷 如果登陸了執行inner裡面的return res實際上是呼叫原函式,比如打開個人詳情頁
# 執行程式,修改if判斷的結果,檢視裝飾器執行的結果
# 當理解了上面的單個裝飾器的時候再理解多個裝飾器,面試題很囂張的
def outer1(func):
functools.wraps(func) # inner.__name__ = func.__name__ inner.__doc__ = func.__doc__ 偽裝的更像主函式而已
def inner1(*args, **kwargs): # 如果func()有引數,那裝飾器之後func就等價於inner函式,所以也需要引數接收
print("原函式執行前的任務1") # 當然也可以直接形象接受引數,前提是你知道原函式的引數,如inner(a,b=1,*args, **kwargs)
if True:
res = func(*args, **kwargs) # 這裡是真正呼叫原函式,原函式如果有引數,這裡肯定也得有引數啊,這裡的引數從inner引數獲取
return res
else:
print("原函式執行後的任務1")
print("反向解析跳轉登陸介面1")
return inner1
def outer2(func):
functools.wraps(func) # inner.__name__ = func.__name__ inner.__doc__ = func.__doc__ 偽裝的更像主函式而已
def inner2(*args, **kwargs): # 如果func()有引數,那裝飾器之後func就等價於inner函式,所以也需要引數接收
print("原函式執行前的任務2") # 當然也可以直接形象接受引數,前提是你知道原函式的引數,如inner(a,b=1,*args, **kwargs)
if True:
res = func(*args, **kwargs) # 這裡是真正呼叫原函式,原函式如果有引數,這裡肯定也得有引數啊,這裡的引數從inner引數獲取
return res
else:
print("原函式執行後的任務2")
print("反向解析跳轉登陸介面2")
return inner2
@outer1
@outer2
def func_s(a, b=1):
print("進入個人詳情頁")
func_s("a", 2)
# 下面按照if的判斷來做多個裝飾的分析
# 首先要明白兩個裝飾器的閉包形式
# func_s = outer1(outer2(func_s)) # 一句話:括號裡面的函式是括號外面的引數也是其內部的func(*args, **kwargs)原函式
# func_s("a", 2)
# 首先看出裝飾器是從上向下執行的,先進入到outer1裡面,經過判斷之後執行裡面的inner1函式,判斷是否進入res = func(*args, **kwargs)
# 在執行outer1時,實際上執行的是inner1閉包函式,最上面說到 func = outer(func)等價於把outer的inner賦值給了func,並且在inner中擴充套件了功能和判斷是否呼叫原函式func
# 所以outer1裡面這個res = func(*args, **kwargs)是誰呢?他就是outer2(func_s),因為他就是outer1的引數,也是他的原函式,是對outer2的功能擴充套件
# 在呼叫outer2(func_s)的時候,就是func_s = inner2了,在inner2中對func_s做了功能擴充套件和判斷是否呼叫原函式func_s
# True True
# 呼叫outer1裝飾器,判斷為真,呼叫res = func(*args, **kwargs)。進入outer2,outer2為真,呼叫func_s
"""
原函式執行前的任務1
原函式執行前的任務2
進入個人詳情頁
"""
# True False
# 呼叫outer1裝飾器,判斷為真,呼叫res = func(*args, **kwargs)。進入outer2,outer2為假,不呼叫func_s
"""
原函式執行前的任務1
原函式執行前的任務2
原函式執行後的任務2
反向解析跳轉登陸介面2
"""
# False True
# 呼叫outer1裝飾器,判斷為假,不呼叫res = func(*args, **kwargs)。不進入outer2,不呼叫func_s
"""
原函式執行前的任務1
原函式執行後的任務1
反向解析跳轉登陸介面1
"""
# False False
# 呼叫outer1裝飾器,判斷為假,不呼叫res = func(*args, **kwargs)。不進入outer2,不呼叫func_s
"""
原函式執行前的任務1
原函式執行後的任務1
反向解析跳轉登陸介面1
"""