Python裝飾器與面向切面編程

1. 概述

裝飾器是一個很著名的設計模式,經常被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼并繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。
Python從語法層為我們提供了非常好的實現裝飾模式的方法。

2. 動機

如果不使用python
裝飾器語法的話,我們如果想轉換一個函數(或換句話說,給函數加上裝飾器,例如將一個普通函數轉變成類函數)的話,代碼看起來是這樣子的:

'''
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

可以想象,函數一多,代碼的可讀性就大大下降了。Python
提供了一個另一種優雅的方法來解決這個問題。修改后的代碼如下:

'''
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

代碼量減少了,可讀性也強了,函數的特性也很直觀。

3. 當前語法

當前Python
的裝飾器語法如下:

@dec2
@dec1
def func(arg1, arg2, ...):
pass

上面的代碼相當于:

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))
4. 裝飾器的更多用法示例

我們可以使用Python
裝飾器來更加直接了當地使用
staticmethod()

classmethod()
內置函數,但裝飾器的作用遠不止于此。

1.例如我們要定義一個函數,當程序退出的時候調用此函數。

def onexit(f):
    import atexit
    atexit.register(f)
    return f
 
@onexit
def func():
...

注意在真實場景中我們可能不會這么做,上面代碼只是用作示例。
2.使用Python
裝飾器實現單例模式。

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance
 
@singleton
class MyClass:
    ...

3.給函數添加屬性。

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.聲明類實現了某些接口。

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.python.org/dev/peps/pep-0318/#examples

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,948評論 18 139
  • # Python 資源大全中文版 我想很多程序員應該記得 GitHub 上有一個 Awesome - XXX 系列...
    aimaile閱讀 26,568評論 6 427
  • “平地泉源觱沸三窟突起雪濤數尺,聲如隱雷,冬夏如一” ——《歷城縣志》 傳聞趵突泉,世人游而其見者,無不咄咄稱奇,...
    信言不美閱讀 441評論 0 2
  • 最近讀了《深度工作》這本書,受益匪淺。這是本被《紐約時報》、《華爾街日報》力薦的暢銷書,曾引發數百萬討論的年度話題...
    AI善待自己閱讀 2,267評論 0 1
  • 晨起感恩 感恩父母生養之恩,供我讀書,從小都沒讓我受過苦,長大后也是一直的為我著想,自己開店了,感恩父親幫我做飯,...
    黃巧珍閱讀 154評論 0 1