轉:http://blog.csdn.net/thy38/article/details/4471421
在《Core Python Programming 2nd》中學習到了裝飾器,這對我來說是個完全陌生的文法,第一遍愣是沒看懂,很有必要記一下。
第一眼看到這個詞Decorator,我聯想到了DP中的Decorator模式,後來才知道完全不是這麼一回事。(再次鄙視一下國內浮躁的部落格,我google了一下,幾乎千篇一律都是什麼鎖同步裝飾器、逾時裝飾器,我對原作者表達敬仰,可是大家都是轉載就不像話了,也是對網路資源的極大浪費,也許真正有價值的博文就湮沒在這片都是一模一樣的東西裡了)
1. 這是個什麼東東?
書上說得不是太清楚,它說類似於Java的AOP(Aspect Oriented Programming,面向方面編程),我對AOP一無所知。根據我對許多例子用法的反覆揣摩,我認為是類似於程式設計語意學中所說的前鍵 與後鍵 的概念(Eiffel中的@pre 與@post )。當然你可以在裝飾器中做比前鍵與後鍵更多的事,如:引入日誌、增加計時邏輯來檢測效能、給函數增加事務的能力。
其實總體說起來,裝飾器其實也就是一個函數,一個用來封裝函數的函數,返回一個修改之後的函數對象,將其重新賦值原來的標識符,並永久喪失對原始函數對象的訪問。
2. 裝飾器文法
(1)無參數裝飾器
[python] view plaincopy
- def deco(func):
- print func
- return func
- @deco
- def foo():pass
- foo()
第一個函數deco是裝飾函數,它的參數就是被裝飾的函數對象。我們可以在deco函數內對傳入的函數對象做一番“裝飾”,然後返回這個對象(記住一定要返回 ,不然外面調用foo的地方將會無函數可用。實際上此時foo=deco(foo))
我寫了個小例子,檢查函數有沒有說明文檔:
[python] view plaincopy
- def deco_functionNeedDoc(func):
- if func.__doc__ == None :
- print func, "has no __doc__, it's a bad habit."
- else:
- print func, ':', func.__doc__, '.'
- return func
- @deco_functionNeedDoc
- def f():
- print 'f() Do something'
- @deco_functionNeedDoc
- def g():
- 'I have a __doc__'
- print 'g() Do something'
- f()
- g()
(2)有參數裝飾器
[cpp] view plaincopy
- def decomaker(arg):
- '通常對arg會有一定的要求'
- """由於有參數的decorator函數在調用時只會使用應用時的參數
- 而不接收被裝飾的函數做為參數,所以必須在其內部再建立
- 一個函數
- """
- def newDeco(func): #定義一個新的decorator函數
- print func, arg
- return func
- return newDeco
- @decomaker(deco_args)
- def foo():pass
- foo()
第一個函數decomaker是裝飾函數,它的參數是用來加強“加強裝飾”的。由於此函數並非被裝飾的函數對象,所以在內部必須至少建立一個接受被裝飾函數的函數,然後返回這個對象(實際上此時foo=decomaker(arg)(foo))
這個我還真想不出什麼好例子,還是見識少啊,只好借用同步鎖的例子了:
[python] view plaincopy
- def synchronized(lock):
- """鎖同步裝飾方法
- !lock必須實現了acquire和release方法
- """
- def sync_with_lock(func):
- def new_func(*args, **kwargs):
- lock.acquire()
- try:
- return func(*args, **kwargs)
- finally:
- lock.release()
- new_func.func_name = func.func_name
- new_func.__doc__ = func.__doc__
- return new_func
- return sync_with_lock
- @synchronized(__locker)
- def update(data):
- """更新計劃任務"""
- tasks = self.get_tasks()
- delete_task = None
- for task in tasks:
- if task[PLANTASK.ID] == data[PLANTASK.ID]:
- tasks.insert(tasks.index(task), data)
- tasks.remove(task)
- delete_task = task
- r, msg = self._refresh(tasks, delete_task)
- return r, msg, data[PLANTASK.ID]
調用時還是updae(data)。
同時還可以將多個裝飾器組合 使用:
[python] view plaincopy
- @synchronized(__locker)
- @deco_functionNeedDoc
- def f():
- print 'f() Do something'
學後的總是感覺就是:裝飾器可以讓函數輕裝上陣,更重要的是將函數的約束放置於介面處,使意圖更加明了,同時又不增加調用者的負擔。
這貼子還是很膚淺的,我一定會回來的 !