1. 程式人生 > >python cookbook第三版學習筆記十九:未包裝的函式新增引數

python cookbook第三版學習筆記十九:未包裝的函式新增引數

比如有下面如下的程式碼,每個函式都需要判斷debug的是否為True,而預設的debugFalse

def a(x,debug=False):

    if debug:

        print('calling a')

 

def b(x,y,z,debug=False):

    if debug:

        print('calling b')

 

def c(x,y,debug=False):

    if debug:

        print('calling c')

上面的程式碼可以編寫一個裝飾器為被包裝的函式新增額外的引數來簡化,但是新增的引數不能影響到該函式已有的呼叫約定。定義如下的一個裝飾器

 

def optional_debug(func):

    @wraps(func)

    def wrapper(*args,debug=False,**kwargs):

        if debug:

            print('Calling',func.__name__)

        return func(*args,**kwargs)

return wrapper

 

@optional_debug

def spam(a,b):

print(a,b)

 

spam(1,2)

>>>1,2

spam(1,2,debug=True)

>>>Calling spam

1,2

 

利用裝飾器給類定義打補丁

我們想檢查一部分類的定義,以此來修改類的行為,但是不想通過繼承或者元類的方式來做

我們可以用一個類裝飾器重寫__getattribute__

def log_getattribute(cls):

    print(cls)

    orig_getattribute=cls.__getattribute__

    def new_getattribute(self,name):

        print('geting:',name)

        return orig_getattribute(self,name)

    cls.__getattribute__=new_getattribute

    return cls

 

@log_getattribute

class A:

    def __init__(self,x):

        self.x=x

    def spam(self):

        pass

 

(1) 首先通過orig_getattribute=cls.__getattribute__將初始的__getattribute__方法賦值給orig_getattribute,便於在new_getattribute呼叫

(2) 然後通過cls.__getattribute__=new_getattribute將類的__getattribute__賦值為new_getattribute,這樣在類中呼叫__getattribute__的時候,其實是呼叫的new_getattribute

(3) 最後return cls

 

a=A(42)

print(a.x)

執行結果:

geting: x

42

 

@font-face { font-family: "Times New Roman"; }@font-face { font-family: "宋體"; }p.MsoNormal { margin: 0pt 0pt 0.0001pt; text-align: justify; font-family: "Times New Roman"; font-size: 10.5pt; }span.msoIns { text-decoration: underline; color: blue; }span.msoDel { text-decoration: line-through; color: red; }div.Section0 { }