【问题标题】:Import path for decorator-wrapped function?装饰器包装函数的导入路径?
【发布时间】:2011-06-24 13:06:06
【问题描述】:

假设我有一个装饰器和一个这样的包装函数:

def squared(method):
    def wrapper(x, y):
        return method(x*x, y*y)
    return wrapper

@squared
def sum(x, y):
    return x+y

我有其他代码想要调用sum 函数的未修饰版本。是否有一个导入技巧可以让我使用这种展开的方法?如果我的代码显示from some.module.path import sum,那么我会得到sum 方法的包装版本,这不是我在这种情况下想要的。 (是的,我知道我可以把它分解成一个辅助方法,但这会破坏我在这里要使用的模式的一些清洁度。)

我可以向装饰器添加额外的“魔法”以提供一些替代符号名称(如orig_sum),然后我可以导入,我只是不知道该怎么做。

【问题讨论】:

    标签: python decorator


    【解决方案1】:
    def unwrap(fn):
        return fn.__wrapped__
    
    def squared(method):
        def wrapper(x, y):
            return method(x*x, y*y)
        wrapper.__wrapped__ = method
        return wrapper
    
    @squared
    def sum(x, y):
        return x+y
    
    sum(2,3)       ->  13
    unwrap(sum)(2,3)  ->  5
    

    【讨论】:

    • 从另一个源文件,可以from foo.squared.wrapper import orig as sum吗?
    • @slacy,我不得不说,IMO,你的建议远没有 Reiner Gerecke 的无装饰器版本“干净”。
    • 顺便说一句,最好是setattr(wrapped, method.__name__, method) :)
    • @slacy:一般来说,据我所知,不——原始函数隐藏在编译后的字节码中。
    • 我真的很喜欢你对 unwrap 助手的使用。事实上,可以把它变成一个装饰器......
    【解决方案2】:

    这个呢?

    def squared(method):
        def wrapper(x, y):
            return method(x*x, y*y)
        return wrapper
    
    def sum(x, y):
        return x+y
    
    squared_sum = squared(sum)
    

    它仍然是一个装饰器,但您仍然可以导入 squared 和 sum 而无需任何魔法。不确定这是否是您所说的“辅助方法”的意思,但我发现这比 sum 方法干净得多,它实际上是对其输入的平方求和。

    【讨论】:

    • 是的,这当然可以,但它不具备 Python 装饰器语法的简洁性。 :) 正如您可能已经猜到的那样,我实际上并没有在我的代码中求和和平方,这只是一个说明我想要的行为的综合示例。但是,你的观点是正确的,也许我不应该使用@decorator 语法。
    • 迟到了,但你可以:@squared def squared_sum(x, y): return sum(x,y)
    猜你喜欢
    • 2011-06-25
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 2017-09-13
    • 1970-01-01
    • 2014-11-07
    • 2018-03-07
    相关资源
    最近更新 更多