在两个python装饰器之间传递变量

在两个python装饰器之间传递变量,python,decorator,chaining,Python,Decorator,Chaining,是否有一种方法可以在应用于同一函数的两个python装饰器之间传递变量?目标是让其中一个装饰师知道另一个也被应用了。我需要以下示例中的类似decobar_present()的内容: def decobar(f): def wrap(): return f() + "bar" return wrap def decofu(f): def wrap(): print decobar_present() # Tells me whether d

是否有一种方法可以在应用于同一函数的两个python装饰器之间传递变量?目标是让其中一个装饰师知道另一个也被应用了。我需要以下示例中的类似decobar_present()的内容:

def decobar(f):
    def wrap():
        return f() + "bar"
    return wrap

def decofu(f):
    def wrap():
        print decobar_present() # Tells me whether decobar was also applied
        return f() + "fu"
    return wrap

@decofu
@decobar
def important_task():
    return "abc"

更一般地说,我希望能够根据是否也应用了decobar来修改decofu的行为

虽然可以操作,但我认为,您最好创建一个函数
decofubar
,并尽可能多地合并“fu”和“bar”。至少,它会使您的代码更干净、更明显。

虽然可以操作,但我认为,您最好创建一个函数
decofubar
,并尽可能多地合并“fu”和“bar”。至少,它会使您的代码更干净、更明显。

每个装饰程序都可以包装另一个函数。传递给
decofu()
的函数是
decobar()
装饰器的结果

只要测试
decobar
包装的特定特性,前提是您可以识别包装:

def decobar(f):
    def wrap():
        return f() + "bar"
    wrap.decobar = True
    return wrap

def decofu(f):
    def wrap():
        print 'decobar!' if getattr(f, 'decobar') else 'not decobar'
        return f() + "fu"
    return wrap
我在包装器函数上使用了一个任意属性,但是您可以尝试测试名称(不是很明确)、签名(可能使用
inspect.getargspec()
等)

这仅限于直接包装


一般来说,你不想把装饰师紧密地结合在一起。制定一个不同的解决方案,只依赖于函数签名或返回值。

每个装饰器都可以包装另一个函数。传递给
decofu()
的函数是
decobar()
装饰器的结果

只要测试
decobar
包装的特定特性,前提是您可以识别包装:

def decobar(f):
    def wrap():
        return f() + "bar"
    wrap.decobar = True
    return wrap

def decofu(f):
    def wrap():
        print 'decobar!' if getattr(f, 'decobar') else 'not decobar'
        return f() + "fu"
    return wrap
我在包装器函数上使用了一个任意属性,但是您可以尝试测试名称(不是很明确)、签名(可能使用
inspect.getargspec()
等)

这仅限于直接包装


一般来说,你不想把装饰师紧密地结合在一起。制定一个不同的解决方案,只依赖于函数签名或返回值。

您可以在
decobar
中为
f
(或者更确切地说是
wrap
)指定标志,如下所示

def decobar(f):
    def wrap():
        return f() + "bar"
    wrap.decobar_applied = True
    return wrap

def decofu(f):
    def wrap():
        if hasattr(f, 'decobar_applied') and f.decobar_applied:
            print decobar_present() # Tells me whether decobar was also applied
        return f() + "fu"
    return wrap

@decofu
@decobar
def important_task():
    return "abc"

您可以像这样在
decobar
中为
f
(或者更确切地说是
wrap
)分配标志

def decobar(f):
    def wrap():
        return f() + "bar"
    wrap.decobar_applied = True
    return wrap

def decofu(f):
    def wrap():
        if hasattr(f, 'decobar_applied') and f.decobar_applied:
            print decobar_present() # Tells me whether decobar was also applied
        return f() + "fu"
    return wrap

@decofu
@decobar
def important_task():
    return "abc"

decobar
应用于函数时,您可以将函数添加到“注册表”,然后检查注册表以确定是否将
decobar
应用于函数。这种方法要求保留原始函数的
\uuuu模块\uuuu
\uuuu名称\uuuu
属性不变(使用
functools.wrapps
覆盖包装函数)


使用一个类来实现
decobar
,因为它将
registry
present()
保存在一个名称空间中(在我看来,这个名称空间比较干净)

当应用
decobar
时,可以将函数添加到“注册表”中,然后稍后检查注册表以确定是否将
decobar
应用于该函数。这种方法要求保留原始函数的
\uuuu模块\uuuu
\uuuu名称\uuuu
属性不变(使用
functools.wrapps
覆盖包装函数)


使用一个类来实现
decobar
,因为它将
registry
present()
保存在一个名称空间中(IMO感觉很干净)

要在两个python装饰器之间传递变量,可以使用修饰函数的关键字参数字典。只是不要忘记在从第二个decorator中调用函数之前,从那里弹出添加的参数

    def decorator1(func):
        def wrap(*args, **kwargs):
            kwargs['cat_says'] = 'meow'
            return func(*args, **kwargs)
        return wrap

    def decorator2(func):
        def wrap(*args, **kwargs):
            print(kwargs.pop('cat_says'))
            return func(*args, **kwargs)
        return wrap


    class C:
        @decorator1
        @decorator2
        def spam(self, a, b, c, d=0):
            print("Hello, cat! What's your favourite number?")
            return a + b + c + d

    x=C()
    print(x.spam(1, 2, 3, d=7))

要在两个python装饰器之间传递变量,可以使用装饰函数的关键字参数字典。只是不要忘记在从第二个decorator中调用函数之前,从那里弹出添加的参数

    def decorator1(func):
        def wrap(*args, **kwargs):
            kwargs['cat_says'] = 'meow'
            return func(*args, **kwargs)
        return wrap

    def decorator2(func):
        def wrap(*args, **kwargs):
            print(kwargs.pop('cat_says'))
            return func(*args, **kwargs)
        return wrap


    class C:
        @decorator1
        @decorator2
        def spam(self, a, b, c, d=0):
            print("Hello, cat! What's your favourite number?")
            return a + b + c + d

    x=C()
    print(x.spam(1, 2, 3, d=7))

你为什么需要这个?这些装饰师在干什么?你为什么需要这个?这些修饰符在做什么?注意:只有在
decofu
decobar
@user2357112:确实没有其他修饰符的情况下,这才有效。注意:只有在
decofu
decobar
@user2357112:确实没有其他修饰符的情况下,这才有效。我想我将为所有人实现一个中央注册表装饰师。谢谢你以上的想法!我想我将为所有装饰者实现一个中央注册中心。谢谢你以上的想法!