2017-09-27 59 views
1

修飾器functools.wrap來電方法functools.update_wrapper爲什麼我們使用`wrap`而不是`update_wrapper`作爲裝飾器?

我想了解需要使用wrap而不是update_wrapper。 爲什麼我們不能使用update_wrapper作爲裝飾,而不是使用wrap

例如:

from functools import update_wrapper 
def wrap1(func): 
    def call_it(*args, **kwargs): 
     """wrap func: call_it1""" 
     print('before call in call_it1') 
     return func(*args, **kwargs) 
    return update_wrapper(call_it, func) 

@wrap1 
def hello1(): 
    """test hello 1""" 
    print('hello world1') 

hello1() 

def wrap3(func): 
    @wraps(func) 
    def call_it(*args, **kwargs): 
     """wrap func: call_it3""" 
     print('before call in call_it3') 
     return func(*args, **kwargs) 
    return call_it 

@wrap3 
def hello3(): 
    """test hello 3""" 
    print('hello world3') 

hello3()  

工作。但爲什麼以下不?

def wrap2(func): 
    @update_wrapper(wrapped=func) # error, see below 
    def call_it(*args, **kwargs): 
     """wrap func: call_it2""" 
     print('before call in call_it2') 
     return func(*args, **kwargs) 
    return call_it 

@wrap2 
def hello2(): 
    """test hello 2""" 
    print('hello world2') 

hello2() 

與錯誤

TypeError: update_wrapper() missing 1 required positional argument: 'wrapper' 

The declarations of wraps and update_wrapper是:

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 

的位置參數wrapper是第一個參數update_wrapper, 那麼爲什麼不接下來call_it作爲wrapper參數update_wrapper

@update_wrapper(wrapped=func) 
def call_it(*args, **kwargs): 

是否有某種方式來使用update_wrapper作爲裝飾,而不是使用wrap

回答

1

使用@作爲裝飾基本上可以歸結爲這樣:

@(value) 
def f(...): 
    ... 

是相同的:

def f(...): 
    ... 

f = (value)(f) 

現在,如果我們把它應用到你的情況:

@update_wrapper(wrapped=func) 
def call_it(*args, **kwargs): 
    ... 
def call_it(*args, **kwargs): 
    ... 

call_it = update_wrapper(wrapped=func)(call_it) 

這裏的問題是,第一次,它只是用第二個參數調用。然後立即引發錯誤。

這是因爲update_wrapper不是用作裝飾器,而是wraps是裝飾器(工廠)。

相關問題