全局切换装饰器的使用

时间:2017-03-01 23:02:42

标签: python python-3.x python-decorators

我正在寻找创建一个全局切换变量来打开和关闭我的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

我可以在main.py中创建一个变量,例如USE_DECORATOR = True在这种情况下,会调用装饰器。如果USE_DECORATOR = False,则调用原始函数。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

装饰器会影响执行后面的函数定义时生成的字节代码(在编译函数调用时运行之前和之后分开)。因此,如果没有使用装饰函数重新加载整个模块,可能唯一可行的方法是根据flag变量的当前设置使包装函数执行不同。

请注意,切换变量必须放在一个可变容器中 - 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

使用除单个函数之外的参数的装饰器本质上是 装饰器工厂 ,它必须创建并返回所使用的实际装饰器。这就是为什么你的问题中的装饰者需要更深层次嵌套。

<强> timing_decorator.py

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