2017-03-01 65 views
0

我在創建一個全局切換變量來打開和關閉我的decorator,具體取決於通過命令行傳遞的參數。全局切換裝飾器的使用

在下面的情況下,我不想在不需要的時候註釋掉@time_md5_comparison,而是根據傳遞的參數,我想要一個全局切換。


main.py

from timing_decorator import time_md5_comparison 

@time_md5_comparison 
def md5_comparison(a, b): 
    if a==b: 
     return True 
    else: 
     return False 

timing_decorator.py

def time_md5_comparison(function): 
    @wraps(function) 
    def wrapper(*args, **kwargs): 
     t1 = time.time() 
     result = function(*args, **kwargs) 
     t2 = time.time() 
     print(str(function.__name__)+" "+ str("%.6f " %(t2 - t1))) 
     return result 
    return wrapper 

我可以創建一個變量,說USE_DECORATOR = true在main.py在裝飾器被調用的情況。如果USE_DECORATOR = False,則調用原始函數。

+3

有什麼問題嗎? – dav1d

+0

我可以創建一個變量,比如USE_DECORATOR = True。py 在這種情況下,調用裝飾器。如果USE_DECORATOR = False,則調用原始函數。 – pmsuresh

+0

看到這個答案 - http://stackoverflow.com/a/28654546/4497519這將是微不足道的,然後切換使用命令行參數。 –

回答

0

裝修影響跟隨它們在執行函數定義時產生(字節碼,其是從之前和獨立當編譯的函數在調用時運行)。因此,在重載帶有裝飾函數的整個模塊的情況下,可能唯一可行的方法是使包裝函數根據標記變量的當前設置不同地執行。

注意切換變量必須放在一個可變的容器中 - 一個list - 所以裝飾的函數會引用它的當前值而不是最初裝飾時的值。


main.py

from timing_decorator import time_md5_comparison 

USE_DECORATOR = [False] 

@time_md5_comparison(USE_DECORATOR) 
def md5_comparison(a, b): 
    if a==b: 
     return True 
    else: 
     return False 

md5_comparison(3, 4) # prints nothing 
USE_DECORATOR[0] = True 
md5_comparison(5, 6) # prints timing info 

它需要比單一功能的其他參數裝飾基本上裝飾工廠必須創建並返回實際使用的裝飾。這就是爲什麼你的問題中的裝飾器需要嵌套更深一層。


def time_md5_comparison(disabled): 
    def decorator(function): 
     @wraps(function) 
     def wrapped(*args, **kwargs): 
      if disabled[0]: 
       result = function(*args, **kwargs) 
      else: 
       t1 = time.time() 
       result = function(*args, **kwargs) 
       t2 = time.time() 
       print(str(function.__name__)+" "+ str("%.6f " %(t2 - t1))) 
      return result 

     return wrapped 

    return decorator 
+0

很好的解釋!謝謝@martineau – pmsuresh

+0

我仍然不確定爲什麼我們使用可變容器,而不僅僅是一個變量。讓我試試以獲得更好的理解。 – pmsuresh

+0

我也有點吃驚,但我相信這是因爲像True和False這樣的內置布爾值是不可變的,就像字符串和整數一樣,所以當你將它們傳遞給一個函數時,它們的值會被傳遞,而不是對他們的引用,因爲他們不能改變。 'list'的內容是可變的,所以它們通過引用傳遞。 – martineau

0

是的。你可以傳入值,或者重置裝飾器。

重置裝飾會是這樣的:

import timing_module 

if NO_USE_DECORATOR: 
    mydecorator = timing_module.empty_decorator 
else: 
    mydecorator = timing_module.time_md5_comparison 


@mydecorator 
def myfunc(args): 
    pass 

很顯然,你不必把它mydecorator。您可以重置time_md5_comparison名稱,以指出您喜歡的任何內容。

跑過值作爲參數使所述邏輯在裝飾,這是清潔器:

#module: timing_module 
def original_time_md5_comparison(fn): 
    """Original code of your decorator here""" 
    # ... 
    pass 

def no_decorator(fn): 
    """Decorator no-op. Just use original function.""" 
    return fn 

def time_md5_comparison(use_decorator = True): 
    if use_decorator: 
     return original_time_md5_comparison 
    else: 
     return no_decorator