【问题标题】:Do python decorators strictly implement the decorator pattern ?python 装饰器是否严格执行装饰器模式?
【发布时间】:2012-01-20 06:09:10
【问题描述】:

我参加了一个关于装饰器模式的会议,其中提供的大多数示例都是用 java 编写的。例如,在下面的示例中,Pizza 对象用两个浇头装饰。

Pizza vegPizza = new ToppingsType1(new ToppingType2(new Pizza()))

在 python 中,我已经看到在这样的场景中使用装饰器

@applyTopping2
@applyTopping1
makePizza():
    pass

虽然在这里我可以看到 makePizza 函数被两个函数修饰,但它与 java 的基于类的方法有很大不同。 我的问题是 python 装饰器是严格实现装饰器模式还是实现有点不同但想法是一样的。

PS:我不确定在哪里查找装饰器模式的标准定义。虽然 wikipedia 给出了一个动态语言 (JS) 的示例,但我的问题仍然很好:)

【问题讨论】:

  • 没有什么能阻止 Python 装饰器成为类。
  • 严格执行装饰器模式?装饰器的外观是否有标准定义?
  • 我认为你有责任去定义什么是“严格的装饰器模式”。 (然后,我们 Python 爱好者可以继续描述为什么严格性无关紧要并为 Python 方法辩护:-))
  • @jsbueno 这很有趣,因为这是真的。无论如何,请检查:stackoverflow.com/questions/739654/…。这是装饰器如何在 Python 中工作的示例。你会看到它是否符合你对设计模式的期望。
  • 我也暗中希望有人会来捍卫 python 方法,但遗憾的是 python wiki 说它们是不同的;(无论如何我不在乎,装饰器模式很高兴知道,但我我现在只使用 python 装饰器:) :)

标签: python design-patterns decorator


【解决方案1】:

你应该 read this 解释什么是 python 的装饰器。

我们谈论的与 Python 相关的“装饰器”与DecoratorPattern [...] 并不完全相同。 Python 装饰器是对 Python 语法的特定更改,它允许我们更方便地更改函数和方法(可能还有未来版本中的类)。这支持DecoratorPattern 的更具可读性的应用程序,但也支持其他用途。

因此,您将能够使用 python 的装饰器实现“经典”装饰器模式,但您将能够使用这些装饰器做更多(有趣的;))事情。

在你的情况下,它可能看起来像:

def applyTopping1(functor):
    def wrapped():
        base_pizza = functor()
        base_pizza.add("mozzarella")
        return base_pizza
    return wrapped

def applyTopping2(functor):
    def wrapped():
        base_pizza = functor()
        base_pizza.add("ham")
        return base_pizza
    return wrapped

然后你会得到一个玛格丽塔:)

【讨论】:

    【解决方案2】:

    不是一个真正的答案,只是一个有趣的例子,说明如何在 Python 中做事 - 与静态语言相比:

    def pizza_topping_decorator_factory(topping):
        def fresh_topping_decorator(pizza_function):
            def pizza_with_extra_topping(*args, **kw):
                return pizza_function(*args, **kw) + ", " + topping
            return pizza_with_extra_topping
        return fresh_topping_decorator
    
    
    mozzarela = pizza_topping_decorator_factory("mozarella")
    anchove = pizza_topping_decorator_factory("anchove")
    
    @anchove
    @mozzarela
    def pizza():
        return "Pizza"
    

    在 Python 控制台上粘贴此代码时:

    >>> 
    >>> print pizza()
    Pizza, mozarella, anchove
    

    【讨论】:

    • 在实际代码中最好不要使用_decorator_factory后缀以提高可读性。
    • @lig - shure - 这里的大多数名字只是上述代码中的一部分乐趣。
    【解决方案3】:

    Python 中的@decorator 语法只不过是语法糖。

    代码

    @decorator
    def foo():
        pass
    

    不过是

    def foo():
        pass
    
    foo = decorator(foo)
    

    最终的结果只是取决于你想要它是什么。

    您可以将 class 用作 decorator,并将使用 foo 作为 __init__ arg 从此类实例化对象。

    您可以使用带有一些参数的对象作为装饰器,如下面的代码所示

    class Decorator(object):
        def __init__(self, arg1, arg2):
            pass
    
        def __call__(self, foo):
            return foo()
    
    @Decorator(arg1_value, arg2_value)
    def foo():
        pass
    

    只有你自己来决定你的代码会是什么样子以及它会做什么,而不是任何模式或来自 java 世界的某个人:)

    【讨论】:

    • 如果遵循这个逻辑,那么“class”关键字在 Python 中就是“语法糖”,对于Decorator = type("Decorator", (object,), dict(__init__=lambda s, foo: setattr(s,"f", foo), __call__=lambda s: s.f()))
    • 但是像函数一样,我们在这里得到一个被调用函数的对象,我们没有
    猜你喜欢
    • 2018-03-10
    • 1970-01-01
    • 2023-03-04
    • 2012-01-09
    • 2013-05-07
    • 1970-01-01
    • 2016-07-25
    • 2021-04-01
    相关资源
    最近更新 更多