Python函数修饰器---当方法前遇到@参数化的修饰器方法时发生的事

xiaoxiao2021-02-28  73

一、前提概念

  Python中的函数是对象。也因此,函数可以被当做变量使用。

二、代码模型

以下代码片段来自于: http://www.sharejs.com/codes/python/8361

# -*- coding: utf-8 -*- from threading import Thread import time class TimeoutException(Exception): pass ThreadStop = Thread._Thread__stop#获取私有函数 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)过程:

执行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

通过函数timelimited(2),可以看到最后返回了decorator函数,其内部参数timeout即为2.此时@timelimited(2)可以看成是@decorator

@decorator

@decorator def somefunction(secs):

python解析器遇到@,且后面跟着函数时,会把函数somefunction当做参数传递给decorator函数并执行,即decorator(somefunction),本例中执行 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

此例中,执行 decorator(fn_1)后返回的是decorator2,decorator2中function参数为fn_1对象,

最后用返回的decorator2函数替换somefunction,本例中是用decorator2替换了原来的fn_1

因此,后面直接调用fn_1(4)时,就是调用了decorator2(4),再在decorator2执行过程中,把参数传给function函数变量执行,最后返回想要的结果。

吐槽一下:感觉示例代码中的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
转载请注明原文地址: https://www.6miu.com/read-50787.html

最新回复(0)