修饰器模式是面向对象编程领域的一种设计模式。 通过向一个类对象动态的添加新的行为而实现。 修饰器可以给某个对象添加一些功能, 而不是整个类添加功能, 所以很灵活。
在python中, 我们可以使用decorators对callable的objects(注意包括functions, methods, 或者类classes)进行一些简单的修饰, 使得这些objects具有一些新的行为。
要理解decorators, 我们必须首先知道, python中, functions也是一个对象, 就想string, variables, class , integers等一样。 函数是根据给定的参数吐出产生的值的。
我们可以将一个函数作为一个参数传递给另一个函数, 也可以将一个函数赋值给一个变量, 或者函数返回一个函数。
如下, 返回一个函数:
def foobar(original_function):
# make a new function
def new_function():
# some code
return new_function
decorator的定义:
一个decorator就是一个function, 吃callable object作为其参数, 然后将添加修饰后的callable obeject(例如函数)作为一个value返回去。
如下例就是对类进行修饰。例如, 下面就是一个修饰器:
def verbose(original_function):
# make a new function that prints a message when original_function starts and finishes
def new_function(*args, **kwargs):
print("Entering", original_function.__name__)
original_function(*args, **kwargs)
print("Exiting ", original_function.__name__)
return new_function
要使用decorator也很简单。
我们可以将一个函数传进去, 得到新一个新的修饰后的函数talkative_widget_func。 如下:
def widget_func():
# some code
talkative_widget_func = verbose(widget_func)
def widget_func():
# some code
widget_func = verbose(widget_func)
注意上述返回的函数命名为widget_func, 和传进去的原始函数一样。
除此之外, python还有一个decortation syntax。 也就是使用“@”去创建decoration lines. 这个feature就是语法糖(syntax sugar), 是的我们可以将上面的例子重新写为如下形式:
@verbose
def widget_func():
# some code
上述产生的结果和上面的增强版本一样了。 这样我们的新的widget_func函数就具有原始的widget_func所有的行为在加上varbose修饰器添加的行为了。
不光可以修饰函数, 也可以对类进行修饰。程序如下:
#!/usr/bin/python
#decotor design pattern
import sys
YELLOW = '\033[93m'
RED = '\033[91m'
NORMAL = '\033[0m'
class Person(object):
def __init__(self, name, age): # constructor
self.name = name
self.age = age
def __str__(self):
return '%s is %s' %(self.name, self.age)
# decorator class to wrapps an object passed in
#for age < 20, print NOEMAL
#for 20 < age < 20, print YELLOW
#for age > 30, print RED
class PersonDecorator(Person):
def __init__(self, person):
self._person = person
def __getattr__(self, name):
return getattr(self._person, name)
def __str__(self):
age = self._person.age
colour = NORMAL
if age >= 30:
colour = RED
elif age >= 20:
colour = YELLOW
return '%s%s%s' %(colour