Python函數修飾器---當方法前遇到@參數化的修飾器方法時發生的事

1、前提概念

  Python中的函數是對象。也所以,函數能夠被當作變量使用。python

2、代碼模型

如下代碼片斷來自於: http://www.sharejs.com/codes/python/8361app

# -*- 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)

3、分析代碼片斷

@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)能夠當作是@decoratorcode

  • @decorator對象

@decorator
        def somefunction(secs):

python解析器遇到@,且後面跟着函數時,會把函數somefunction當作參數傳遞給decorator函數並執行,即decorator(somefunction),本例中執行 decorator(fn_1)utf-8

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對象,get

  • 最後用返回的decorator2函數替換somefunction,本例中是用decorator2替換了原來的fn_1it

所以,後面直接調用fn_1(4)時,就是調用了decorator2(4),再在decorator2執行過程當中,把參數傳給function函數變量執行,最後返回想要的結果。io

吐槽一下:感受示例代碼中的decorator2命名爲wrapper會更合適一點

昨晚看Python in Practice看的興奮了,睡不着,以爲今天得記錄下,因此寫了這篇文章,不足或錯誤之處,請你們指正,謝謝!

參考文章

疑問:

若是一個做者,在一個網站上發表了文章,若是須要在另外一個網站上再發表,需不須要聲明成轉載或是須要其餘什麼的說明,麻煩解答一下。

附:本人簡書地址

相關文章
相關標籤/搜索