Python函数修饰器—当方法前遇到@参数化的修饰器方法时发生的事
admin
2023-07-31 01:45:27
0

一、前提概念

  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

疑问:

如果一个作者,在一个网站上发表了文章,如果需要在另一个网站上再发表,需不需要声明成转载或是需要其他什么的说明,麻烦解答一下。

附:本人简书地址

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python查找阿姆斯特朗数 题目解释 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数。 例如1^3 + 5...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...