Python 装饰器严格遵循装饰者模式吗?
我参加过一个关于装饰器模式的讲座,里面大部分例子都是用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
然后你就能得到一个玛格丽塔披萨了 :)