资讯专栏INFORMATION COLUMN

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

huashiou / 3501人阅读

一、前提概念

  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.ucloud.cn/yun/45436.html

相关文章

  • Python 的闭包和装饰

    摘要:所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 对于已经对 闭包 或者 装饰器有一定概念的,可以直接通过右侧标题目录直接定位到相应段落查看所需的内容。 什么是装饰器? 装饰器(Decorator)相对简单,咱们先介绍它:装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数,听起来有点绕,没关系,直接看示意图,...

    justCoding 评论0 收藏0
  • 简单聊聊Python中的wraps修饰

    摘要:首先说函数,在官方文档的描述中,这个函数的声明如下。这是因为给添加上修饰器相当于执行了一句,执行完这条语句之后,函数就变成了函数。自定义修饰器我们对上面定义的修饰器稍作修改,添加了一句。参考链接装饰器和模块源码 预备知识 在了解wraps修饰器之前,我们首先要了解partial和update_wrapper这两个函数,因为在wraps的代码中,用到了这两个函数。 partial 首先说...

    Jensen 评论0 收藏0
  • 聊聊Typescript中的设计模式——装饰篇(decorators)

    摘要:本文从装饰模式出发,聊聊中的装饰器和注解。该函数的函数名。不提供元数据的支持。中的元数据操作可以通过包来实现对于元数据的操作。   随着Typescript的普及,在KOA2和nestjs等nodejs框架中经常看到类似于java spring中注解的写法。本文从装饰模式出发,聊聊Typescipt中的装饰器和注解。 什么是装饰者模式 Typescript中的装饰器 Typescr...

    yiliang 评论0 收藏0
  • python中的装饰

    摘要:的装饰器是用来装饰函数的。简单装饰器装饰器的语法糖是使用符号表示,装饰器本身也是一个函数,只不过参数是函数而已。保留函数的元信息被修饰之后的函数,它的元信息都消失,被替换的函数代替。中提供了来保存函数的元信息。 python的装饰器是用来装饰函数的。这是什么意思呢?假如我们有一个函数,这个函数的功能不能满足我们现有的需求,那么我们可以通过装饰器在这个函数执行前执行后做一些我们需要的操作...

    张金宝 评论0 收藏0
  • Python有什么好学的》之修饰

    摘要:然后煎鱼加了一个后再调用函数,得到的输出结果和加修饰器的一样,换言之等效于因此,我们对于,可以理解是,它通过闭包的方式把新函数的引用赋值给了原来函数的引用。 Python有什么好学的这句话可不是反问句,而是问句哦。 主要是煎鱼觉得太多的人觉得Python的语法较为简单,写出来的代码只要符合逻辑,不需要太多的学习即可,即可从一门其他语言跳来用Python写(当然这样是好事,谁都希望入门简...

    lewinlee 评论0 收藏0

发表评论

0条评论

huashiou

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<