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

一、前提概念

  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>>看的兴奋了,睡不着,觉得今天得记录下,所以写了这篇文章,不足或错误之处,请大家指正,谢谢!

参考文章

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值