1. 概述
裝飾器是一個(gè)很著名的設(shè)計(jì)模式,經(jīng)常被用于有切面需求的場(chǎng)景,較為經(jīng)典的有插入日志、性能測(cè)試、事務(wù)處理等。裝飾器是解決這類問(wèn)題的絕佳設(shè)計(jì),有了裝飾器,我們就可以抽離出大量函數(shù)中與函數(shù)功能本身無(wú)關(guān)的雷同代碼并繼續(xù)重用。概括的講,裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能。
Python從語(yǔ)法層為我們提供了非常好的實(shí)現(xiàn)裝飾模式的方法。
2. 動(dòng)機(jī)
如果不使用python裝飾器語(yǔ)法的話,我們?nèi)绻朕D(zhuǎn)換一個(gè)函數(shù)(或換句話說(shuō),給函數(shù)加上裝飾器,例如將一個(gè)普通函數(shù)轉(zhuǎn)變成類函數(shù))的話,代碼看起來(lái)是這樣子的:
'''
Created on 2011-12-14
@author: Ahan
'''
class Foo(object):
def foo(self):
print("foo is called")
pass
#Turn the method foo to a class method
foo = classmethod(foo)
if __name__ == '__main__':
Foo.foo()
pass
可以想象,函數(shù)一多,代碼的可讀性就大大下降了。Python提供了一個(gè)另一種優(yōu)雅的方法來(lái)解決這個(gè)問(wèn)題。修改后的代碼如下:
'''
Created on 2011-12-14
@author: Ahan
'''
class Foo(object):
#Turn the method foo to a class method
@classmethod
def foo(self):
print("foo is called")
pass
if __name__ == '__main__':
Foo.foo()
pass
代碼量減少了,可讀性也強(qiáng)了,函數(shù)的特性也很直觀。
3. 當(dāng)前語(yǔ)法
當(dāng)前Python的裝飾器語(yǔ)法如下:
@dec2
@dec1
def func(arg1, arg2, ...):
pass
上面的代碼相當(dāng)于:
def func(arg1, arg2, ...):
pass
func = dec2(dec1(func))
4. 裝飾器的更多用法示例
我們可以使用Python裝飾器來(lái)更加直接了當(dāng)?shù)厥褂?/font>staticmethod() 和classmethod()內(nèi)置函數(shù),但裝飾器的作用遠(yuǎn)不止于此。
1.例如我們要定義一個(gè)函數(shù),當(dāng)程序退出的時(shí)候調(diào)用此函數(shù)。
def onexit(f):
import atexit
atexit.register(f)
return f
@onexit
def func():
...
注意在真實(shí)場(chǎng)景中我們可能不會(huì)這么做,上面代碼只是用作示例。
2.使用Python裝飾器實(shí)現(xiàn)單例模式。
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
@singleton
class MyClass:
...
3.給函數(shù)添加屬性。
def attrs(**kwds):
def decorate(f):
for k in kwds:
setattr(f, k, kwds[k])
return f
return decorate
@attrs(versionadded="2.2",
author="Guido van Rossum")
def mymethod(f):
...
4.聲明類實(shí)現(xiàn)了某些接口。
def provides(*interfaces):
"""
An actual, working, implementation of provides for
the current implementation of PyProtocols. Not
particularly important for the PEP text.
"""
def provides(typ):
declareImplementation(typ, instancesProvide=interfaces)
return typ
return provides
class IBar(Interface):
"""Declare something about IBar here"""
@provides(IBar)
class Foo(object):
"""Implement something here..."""
參考資料:http://www./dev/peps/pep-0318/#examples