本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/88032
python裝飾器
裝飾器本質是一個裝飾器函數,在不改變一個函數的函數體本身的情況下,實現函數體本身外其他的功能
1.實現一個裝飾器
def ?logger(fn): ? ? ? ? ? ? ? ? ? ? ? ? #裝飾器函數必須只能傳入一個參數,那就是被裝飾函數
????print(‘in’)
????def wrapper(*args,**kwargs):
?? ?? ? print(‘before’)
????????ret = fn(*args,**kwargs)
?? ?? ? print(‘after’)
????????return ret
????return wrapper
@logger
def foo3(x=3,y=4): ? ? ? #相當于 ? foo3=logger(foo3)
? ? ”’i’m foo3”’
????print(x,y)
?代碼在加載時就會打印 ?‘in’
執行foo3函數相當于執行下面的函數 ? ?執行foo3(參數) ,args 和kwargs會獲取實際輸入的位置參數和關鍵字參數,然后傳給原函數中調用(它不會獲取原函數中的默認參數值,但這不會改變函數執行結果).
def wrapper(*args,**kwargs):
? ? print(‘before’)
? ? ret = foo3(*args,**kwargs)
? ? print(‘after’)
? ? return ret
2.文檔字符串 和 帶參數的裝飾器
一個函數定義之后就會有對應的文檔字符(.__doc__)等屬性生成. 裝飾器函數包裝過后,獲取不到原函數的各種屬性就變成了wrapper對應的屬性
下面使用了一個帶有參數的裝飾器把wrapper 函數裝飾成一個新的wrapper函數,這里使用到了一個帶有參數的裝飾器
代碼2.1:
def copy_properties(src):
?? ?def _copy(dst):
?? ??? ?dst.__name__ = src.__name__
?? ??? ?dst.__doc__ = src.__doc__
?? ??? ?return dst
?? ?return _copy
def logger(fn):
?? ?@copy_properties(fn) ? ? ? ? ?# wrapper = wrapper(fn)(wrapper)
?? ?def wrapper(*args,**kwargs):
?? ??? ??‘I am wrapper’
?? ??? ?print(‘begin’)
?? ??? ?x = fn(*args,**kwargs)
?? ??? ?print(‘end’)
?? ??? ?return x
?? ??return wrapper
@logger ? ? ? ? ? ?#add = logger(add)
?def add(x,y):
?? ??”’This is a function for add”’
?? ??? ??return x + y
?print(“name={}, doc={}”.format(add.__name__, add.__doc__))
代碼2.2:
def copy_property(src):
????def _copy(dst):
?? ?? ? print(11)
????????dst.__name__ = src.__name__
????????dst.__doc__ = src.__doc__
????????return dst
????return _copy
def add(x,y):
????”’i am add”’
????print(x,y)
????return x+y
@copy_property(add)
def wrapper(*args,**kwargs): ? ? ? ?#wrapper = cop_property(add) (wrapper)
????”’i am wrapper”’
? ? print(22)
????ret = add(*args,**kwargs)
????return ret
print(add.__name__,add.__doc__)
print(wrapper.__name__,wrapper.__doc__)
運行代碼2.2 ?會加載裝飾器 運行右邊的?wrapper = cop_property(add) (wrapper)?程序 ?,add的屬性會賦給 wrapper,打印如下.
11?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? 如果執行wrapper(2,3) ?會 先打印 22,然后執行add中的過程
add i am add
add i am add
3.對一個函數使用多個裝飾器
def decorator1(func):
????print(11)
????def wrapper1(*args,**kwargs):
????????print(‘hello python 之前’)
????????ret=func(*args,**kwargs)
????????return ret
????return wrapper1
def decorator2(func):
????print(22)
????def wrapper2(*args,**kwargs):
????????print(‘hello python 之后’)
????????ret=func(*args,**kwargs)
????????return ret
????return wrapper2
@decorator1
@decorator2
def test(x,y):
????print(‘hello python!’,x,y)
test(4,5)
22 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對一個函數執行多個裝飾器,執行結果相當于對decorator2裝飾test的函數 再使用decorator1裝飾它
11
hello python 之前
hello python 之后
hello python! 4 5
贊 (0)