Python 装饰器严格遵循装饰者模式吗?

3 投票
3 回答
834 浏览
提问于 2025-04-17 08:22

我参加过一个关于装饰器模式的讲座,里面大部分例子都是用Java写的。例如,下面这个例子中,Pizza对象被加上了两个配料。

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

在Python中,我见过装饰器被用在这样的场景里。

@applyTopping2
@applyTopping1
makePizza():
    pass

虽然在这里我看到makePizza函数被两个函数装饰,但这和Java的类基础方法差别很大。我的问题是,Python的装饰器是否严格遵循装饰器模式,还是说实现上有点不同,但核心思想是一样的。

另外,我不太确定在哪里能找到装饰器模式的标准定义。虽然维基百科给了一个动态语言(JavaScript)的例子,但我的问题依然有效 :)

3 个回答

1

在Python中,@decorator的语法其实就是一种语法糖。

这段代码

@decorator
def foo():
    pass

其实就是

def foo():
    pass

foo = decorator(foo)

最终的结果完全取决于你想要它是什么样子的。

你可以把类当作decorator来用,这样就会得到一个用foo作为__init__参数实例化的对象。

你也可以用带有一些参数的实例化对象作为装饰器,就像下面的代码一样

class Decorator(object):
    def __init__(self, arg1, arg2):
        pass

    def __call__(self, foo):
        return foo()

@Decorator(arg1_value, arg2_value)
def foo():
    pass

最终决定你代码样子和功能的,只有你自己,而不是任何模式或Java世界里的人:)

1

这不是一个真正的答案,只是一个有趣的例子,展示了在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
2

你应该去看看这个链接,它解释了什么是Python的装饰器。

我们所说的Python的“装饰器”,和装饰者模式并不完全一样。Python的装饰器是一种特定的语法变化,它让我们可以更方便地修改函数和方法(未来的版本可能还会支持类)。这不仅支持了更易读的装饰者模式的应用,还有其他更多的用法。

所以,你可以用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

然后你就能得到一个玛格丽塔披萨了 :)

撰写回答