1. 程式人生 > 實用技巧 >消除裝飾器對原函式的屬性影響

消除裝飾器對原函式的屬性影響


首先介紹Python的"萬能"裝飾器模版:

import os
def decor(func):
    def with_decor(*args, **kwargs):  #這裡內部巢狀函式使原函式引數能順利傳遞
        func(*args, **kwargs)  #func_A 會在這裡被呼叫
        a = args
        print(a)
    print('call decor')
    return with_decor

@decor
def func_A(*args, **kwargs):
    print('call A')
    
func_A(
1,2,3) os.system("pause")

  該程式將會輸出:

  

  呼叫 func_A 函式會執行直接裝飾器裡的內容,並將引數傳入閉包


然後介紹一下這種一般裝飾器的副作用:

  python裝飾器會使原函式的屬性被改變,比如func.__name__

  這裡新增一行 print(func_A.__name__)來展示影響

  輸出效果:

  可以看到原函式 func_A的名字變成了裝飾器裡面的函式with_decor的名字

  這導致一些特殊場合要用到這些屬性時不方便,比如在 Robot Framework自動化測試框架中呼叫函式,函式被裝飾後就不能被正常呼叫


因此可採用from functools import wraps,避免這種影響:

import os
from functools import wraps
def decor(func):
    @wraps(func)
    def with_decor(*args, **kwargs):
        return func(*args, **kwargs)
    return with_decor

@decor
def func_A(*args, **kwargs):
    print('call A')
    
func_A(1,2,3)
print(func_A.__name__)
os.system("pause")

  輸出:  可以看到原函式的屬性沒有被改變

  wraps 的作用可以理解為消除裝飾器的影響