一颖低、前提概念
Python中的函數(shù)是對象拷窜。也因此俭茧,函數(shù)可以被當做變量使用咆疗。
二、代碼模型
以下代碼片段來自于: http://www.sharejs.com/codes/python/8361
# -- coding: utf-8 --
from threading import Thread
import time
class TimeoutException(Exception):
pass
ThreadStop = Thread._Thread__stop#獲取私有函數(shù)
def timelimited(timeout):
def decorator(function):
def decorator2(*args,**kwargs):
class TimeLimited(Thread):
def __init__(self,_error= None,):
Thread.__init__(self)
self._error = _error
def run(self):
try:
self.result = function(*args,**kwargs)
except Exception,e:
self._error =e
def _stop(self):
if self.isAlive():
ThreadStop(self)
t = TimeLimited()
t.start()
t.join(timeout)
if isinstance(t._error,TimeoutException):
t._stop()
raise TimeoutException('timeout for %s' % (repr(function)))
if t.isAlive():
t._stop()
raise TimeoutException('timeout for %s' % (repr(function)))
if t._error is None:
return t.result
return decorator2
return decorator
@timelimited(2)
def fn_1(secs):
time.sleep(secs)
return 'Finished'
if __name__ == "__main__":
print fn_1(4)
三母债、分析代碼片段
@timelimited(2)
def fn_1(secs):
time.sleep(secs)
return 'Finished'
解析@timelimited(2)過程:
-
執(zhí)行timelimited(2)
def timelimited(timeout):
def decorator(function):
def decorator2(args,*kwargs):
.......
t.join(timeout)if isinstance(t._error,TimeoutException): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t.isAlive(): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t._error is None: return t.result return decorator2 return decorator
通過函數(shù)timelimited(2),可以看到最后返回了decorator函數(shù)民傻,其內(nèi)部參數(shù)timeout即為2.此時@timelimited(2)可以看成是@decorator
-
@decorator
@decorator
def somefunction(secs):
python解析器遇到@,且后面跟著函數(shù)時场斑,會把函數(shù)somefunction當做參數(shù)傳遞給decorator函數(shù)并執(zhí)行,即
decorator(somefunction)牵署,本例中執(zhí)行 decorator(fn_1)
def decorator(function):
def decorator2(args,*kwargs):
.......
t.join(timeout)if isinstance(t._error,TimeoutException): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t.isAlive(): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t._error is None: return t.result return decorator2
此例中漏隐,執(zhí)行 decorator(fn_1)后返回的是decorator2,decorator2中function參數(shù)為fn_1對象奴迅,
最后用返回的decorator2函數(shù)替換somefunction青责,本例中是用decorator2替換了原來的fn_1
因此,后面直接調(diào)用fn_1(4)時取具,就是調(diào)用了decorator2(4)脖隶,再在decorator2執(zhí)行過程中,把參數(shù)傳給function函數(shù)變量執(zhí)行暇检,最后返回想要的結(jié)果产阱。
吐槽一下:感覺示例代碼中的decorator2命名為wrapper會更合適一點
昨晚看<<Python in Practice>>看的興奮了,睡不著块仆,覺得今天得記錄下构蹬,所以寫了這篇文章王暗,不足或錯誤之處,請大家指正庄敛,謝謝俗壹!
參考文章
- How can I make a chain of function decorators in Python?
- <<Python in Practice>>
- http://www.sharejs.com/codes/python/8361