首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在全球范围内切换装饰师的用法?

如何在全球范围内切换装饰师的用法?
EN

Stack Overflow用户
提问于 2017-03-01 23:02:42
回答 2查看 680关注 0票数 2

根据通过命令行传递的参数,我希望创建一个全局切换变量来打开和关闭我的装饰。

在下面的例子中,我不需要在不需要时注释掉@time_md5_comparison,而是根据传递的参数进行全局切换。

main.py

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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 = Truemain.py中,这样就可以调用装饰器,如果它后来被设置为False,那么原始函数就会被调用?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-02 01:17:50

装饰器会影响在执行它们之后的函数定义时生成的字节码(在被调用时,它与编译后的函数本身运行时是分开的)。因此,如果不重新加载整个模块中的修饰函数,那么唯一可行的方法可能是根据标志变量的当前设置,使包装函数以不同的方式执行。

注意,切换变量必须放在可变容器中,这是一个list-so,修饰后的函数将引用它的当前值,而不是最初修饰时的值。

main.py

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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
票数 2
EN

Stack Overflow用户

发布于 2017-03-02 00:35:35

是。您可以传递值,也可以简单地重置装饰器。

重新设置装饰者会是这样的:

代码语言:javascript
运行
复制
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名称,以指向您喜欢的任何内容。

将值作为参数传递给装饰器中的逻辑,这是比较干净的:

代码语言:javascript
运行
复制
#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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42543800

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档