python: 設計模式(design pattern)之修飾器模式(decorator)
修飾器模式是物件導向程式設計領域的一種設計模式。 通過向一個類物件動態的新增新的行為而實現。 修飾器可以給某個物件新增一些功能, 而不是整個類新增功能, 所以很靈活。
在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, self._person.__str__(), NORMAL)
def main():
p = [] # list of person
p.append(Person('Micheal', 25))
p.append(Person('Kate', 2))
p.append(Person('Mark', 48))
p.append(Person('Matt', 21))
for person in p:
if '-c' in sys.argv:
person = PersonDecorator(person)
print person
if __name__ == '__main__':
main()
執行結果如下:附錄: 解釋(stackoverflow摘錄)
*args and **kwargs
Similarly, **kwargs
allows
you to handle named arguments that you have not defined in advance:
如下:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print '{0} = {1}'.format(name, value)
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
You can also use both in the same function definition but *args
must
occur before **kwargs
.http://www.wklken.me/posts/2013/12/21/how-to-use-args-and-kwargs-in-python.html
解釋如下:在函式中使用*和**是用於傳遞可變長引數, *args用於傳遞非命名剪枝可變長引數列表。 **kwargs用作傳遞鍵值可變長引數列表。 如下, 傳遞一個位置引數和兩個可變長引數。
def test_var_args(farg, *args):
print "formal arg:", farg
for arg in args:
print "another arg:", arg
test_var_args(1, "two", 3)
def test_var_kwargs(farg, **kwargs):
print "formal arg:", farg
for key in kwargs:
print "another keyword arg: %s: %s" % (key, kwargs[key])
test_var_kwargs(farg=1, myarg2="two", myarg3=3)
執行結果如下:
上述語法也可以出現在呼叫函式中, 如下:
def test_var_args_call(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
args = ("two", 3)
test_var_args_call(1, *args)
如下:
或者:
def test_var_args_call(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
kwargs = {"arg3": 3, "arg2": "two"} #ie dictionary
test_var_args_call(1, **kwargs)
相關文章
- 設計模式之裝飾器模式(decorator pattern)設計模式
- JAVA設計模式之 裝飾模式【Decorator Pattern】Java設計模式
- 設計模式--裝飾模式(Decorator Pattern)設計模式
- 設計模式-裝飾模式(Decorator Pattern)設計模式
- Java設計模式之裝飾者模式(Decorator pattern)Java設計模式
- C#設計模式-裝飾器模式(Decorator Pattern)C#設計模式
- PHP設計模式(六)—裝飾器模式(Decorator Pattern)PHP設計模式
- C++ 設計模式 裝飾模式(Decorator Pattern)C++設計模式
- Net設計模式例項之裝飾者模式(Decorator Pattern)設計模式
- PHP設計模式之裝飾器模式(Decorator)PHP設計模式
- 裝飾模式 (Decorator Pattern)模式
- PHP設計模式- Decorator 裝飾器模式PHP設計模式
- java設計模式-裝飾器模式(Decorator)Java設計模式
- 常用開源框架中設計模式使用分析- 裝飾器模式(Decorator Pattern)框架設計模式
- 設計模式--裝飾器模式Decorator(結構型)設計模式
- 設計模式 (十)裝飾模式(Decorator)設計模式
- Decorator裝飾設計模式設計模式
- 裝飾器模式(Decorator)模式
- 前端常用設計模式(1)--裝飾器(decorator)前端設計模式
- C#設計模式系列:裝飾模式(Decorator)C#設計模式
- [Design Pattern With Go]設計模式-工廠模式Go設計模式
- 設計模式之-裝飾器模式設計模式
- 設計模式之【裝飾器模式】設計模式
- 設計模式的征途—10.裝飾(Decorator)模式設計模式
- Python設計模式-裝飾器模式Python設計模式
- JAVA設計模式之 迭代器模式【Iterator Pattern】Java設計模式
- Go 設計模式之裝飾器模式Go設計模式
- java設計模式之裝飾器模式Java設計模式
- 七、GO 程式設計模式: 修飾器Go程式設計設計模式
- Decorator裝飾模式模式
- 什麼是設計模式?(Design Pattern)設計模式
- 【趣味設計模式系列】之【裝飾器模式】設計模式
- Java學設計模式之裝飾器模式Java設計模式
- python函式修飾器(decorator)Python函式
- 設計模式之代理模式(proxy pattern)設計模式
- 【設計模式之裝飾模式】設計模式
- 設計模式之裝飾模式設計模式
- 6、Python與設計模式–裝飾器模式Python設計模式