为什么"包装"装饰者的名字比“加法器”更好?#34;?

时间:2017-11-30 01:48:26

标签: python wrapper

装饰者的一个简单例子是:

def strong(func):
    def wrapper():
        return '<strong>' + func() + '</strong>'
    return wrapper
@strong
def greet():
    return 'Hello!'

wrapper是&#39;内部一阶函数&#39;在高阶函数strong内。

我的问题是wrapper这个词除了混淆新手之外没有任何实际意义。为什么不使用&#39; adder&#39;,因为它可以直观地辨别出来?

  

Decorator pattern - Wikipedia   在面向对象的编程中,装饰器模式是一种设计模式,允许将行为添加静态或动态地添加到单个对象,而不会影响同一类中其他对象的行为。[1 ]

维基百科的解释中的关键词已添加&#39;

Cambridge English Dictionary

  

添加内容添加到对象或地点,尤其是为了使其更具吸引力:

关键字也是&#39;添加&#39;。

那么为什么wrapper优于&#39;加法&#39;?

1 个答案:

答案 0 :(得分:1)

当您使用装饰器时,您已将原始代码包装在另一个函数中,使原始函数不可见。继续你的例子,

def strong(func):
    def wrapper():
        return '<strong>' + func() + '</strong>'
    return wrapper
@strong
def greet():
    return 'Hello!'

def weak_greet():
    return 'hi'

print(greet)
print(weak_greet)

如果你运行它,你会得到以下输出。

<function strong.<locals>.wrapper at 0x000000000129A268>
<function weak_great at 0x000000000129A2F0>

当你使用装饰器时,你接受了你的功能,创建了一个新函数,它将代码包裹在旧函数周围并返回新的匿名函数。

如果你试图腌制它,你可以看到一些不愉快的效果。

如果您执行pickle.dumps(weak_greet),则会获得b'\x80\x03c__main__\nweak_great\nq\x00.'。但如果您尝试pickle.dumps(greet),则会获得AttributeError: Can't pickle local object 'strong.<locals>.wrapper'。 (处理必须被腌制的装饰类和功能是地狱之一,我不希望很快再次访问)。

您没有添加到您的功能。您将原始功能包装在一个闪亮的新功能中。这个新功能说:“我有一些东西藏在这里,我不会告诉你它是什么(functools.wraps有时可以帮助你,就像你的情况一样)。但是,当你给我输入时,我会改变它(或根本不改变它),将它传递给我的秘密函数,(可能)改变输出并给你。你的原始函数是不可访问的(因此pickle的混乱)。

注意:您可以通过使用@functools.wraps(original_function)进一步包装您的包装器来重新创建原始函数的外观,这不会影响输出,但会将所有内容包装在一个框中以使其成为可能看起来与原始功能完全一样。所以,

from functools import wraps
def strong(func):
    @wraps(func)
    def wrapper():
        return '<strong>' + func() + '</strong>'
    return wrapper

现在看起来像你原来的功能,并且可以腌制。这就像包装一个惊喜礼物,然后用包装纸再次包装礼物,告诉你(非常详细)惊喜是什么。