根据通过命令行传递的参数,我希望创建一个全局切换变量来打开和关闭我的装饰。
在下面的例子中,我不需要在不需要时注释掉@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 Falsetiming_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中,这样就可以调用装饰器,如果它后来被设置为False,那么原始函数就会被调用?
发布于 2017-03-02 01:17:50
装饰器会影响在执行它们之后的函数定义时生成的字节码(在被调用时,它与编译后的函数本身运行时是分开的)。因此,如果不重新加载整个模块中的修饰函数,那么唯一可行的方法可能是根据标志变量的当前设置,使包装函数以不同的方式执行。
注意,切换变量必须放在可变容器中,这是一个list-so,修饰后的函数将引用它的当前值,而不是最初修饰时的值。
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
from functools import wraps
import time
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发布于 2017-03-02 00:35:35
是。您可以传递值,也可以简单地重置装饰器。
重新设置装饰者会是这样的:
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_decoratorhttps://stackoverflow.com/questions/42543800
复制相似问题