精华内容
下载资源
问答
  • python装饰器详解

    万次阅读 多人点赞 2017-08-14 22:04:28
    简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。 一般而言,我们要想...
    你会Python嘛?
    我会!
    那你给我讲下Python装饰器吧!
    Python装饰器啊?我没用过哎
    

    以上是我一个哥们面试时候发生的真实对白。

    ----------------------------------------------分割线------------------------------------------------------------------------------

    简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
    一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:

    import time
    def func():
        print("hello")
        time.sleep(1)
        print("world")
    

    这是我们最原始的的一个函数,然后我们试图记录下这个函数执行的总时间,那最简单的做法就是:

    #原始侵入,篡改原函数
    import time
    def func():
        startTime = time.time()
        
        print("hello")
        time.sleep(1)
        print("world")
        endTime = time.time()
        
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    
    

    但是如果你的Boss在公司里面和你说:“小祁,这段代码是我们公司的核心代码,你不能直接去改我们的核心代码。”那该怎么办呢,我们仿照装饰器先自己试着写一下:

    #避免直接侵入原函数修改,但是生效需要再次执行函数
    import time
    
    def deco(func):
        startTime = time.time()
        func()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    
    
    def func():
        print("hello")
        time.sleep(1)
        print("world")
    
    if __name__ == '__main__':
        f = func
        deco(f)#只有把func()或者f()作为参数执行,新加入功能才会生效
        print("f.__name__ is",f.__name__)#f的name就是func
    

    这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。然后你可以拍着胸脯对老板说,看吧,不用动你原来的代码,我照样拓展了它的函数功能。
    然后你的老板有对你说:“小祁,我们公司核心代码区域有一千万个func()函数,从func01()到func1kw(),按你的方案,想要拓展这一千万个函数功能,就是要执行一千万次deco()函数,这可不行呀,我心疼我的机器。”
    好了,你终于受够你老板了,准备辞职了,然后你无意间听到了装饰器这个神器,突然发现能满足你闫博士的要求了。
    我们先实现一个最简陋的装饰器,不使用任何语法糖和高级语法,看看装饰器最原始的面貌:

    #既不需要侵入,也不需要函数重复执行
    import time
    
    def deco(func):
        def wrapper():
            startTime = time.time()
            func()
            endTime = time.time()
            msecs = (endTime - startTime)*1000
            print("time is %d ms" %msecs)
        return wrapper
    
    
    @deco
    def func():
        print("hello")
        time.sleep(1)
        print("world")
    
    if __name__ == '__main__':
        f = func #这里f被赋值为func,执行f()就是执行func()
        f()
    

    这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。
    所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

    #带有参数的装饰器
    import time
    
    def deco(func):
        def wrapper(a,b):
            startTime = time.time()
            func(a,b)
            endTime = time.time()
            msecs = (endTime - startTime)*1000
            print("time is %d ms" %msecs)
        return wrapper
    
    
    @deco
    def func(a,b):
        print("hello,here is a func for add :")
        time.sleep(1)
        print("result is %d" %(a+b))
    
    if __name__ == '__main__':
        f = func
        f(3,4)
        #func()
    

    然后你满足了Boss的要求后,Boss又说:“小祁,我让你拓展的函数好多可是有参数的呀,有的参数还是个数不定的那种,你的装饰器搞的定不?”然后你嘿嘿一笑,深藏功与名!

    #带有不定参数的装饰器
    import time
    
    def deco(func):
        def wrapper(*args, **kwargs):
            startTime = time.time()
            func(*args, **kwargs)
            endTime = time.time()
            msecs = (endTime - startTime)*1000
            print("time is %d ms" %msecs)
        return wrapper
    
    
    @deco
    def func(a,b):
        print("hello,here is a func for add :")
        time.sleep(1)
        print("result is %d" %(a+b))
    
    @deco
    def func2(a,b,c):
        print("hello,here is a func for add :")
        time.sleep(1)
        print("result is %d" %(a+b+c))
    
    
    if __name__ == '__main__':
        f = func
        func2(3,4,5)
        f(3,4)
        #func()
    
    

    最后,你的老板说:“可以的,小祁,我这里一个函数需要加入很多功能,一个装饰器怕是搞不定,装饰器能支持多个嘛"
    最后你就把这段代码丢给了他:

    #多个装饰器
    
    import time
    
    def deco01(func):
        def wrapper(*args, **kwargs):
            print("this is deco01")
            startTime = time.time()
            func(*args, **kwargs)
            endTime = time.time()
            msecs = (endTime - startTime)*1000
            print("time is %d ms" %msecs)
            print("deco01 end here")
        return wrapper
    
    def deco02(func):
        def wrapper(*args, **kwargs):
            print("this is deco02")
            func(*args, **kwargs)
    
            print("deco02 end here")
        return wrapper
    
    @deco01
    @deco02
    def func(a,b):
        print("hello,here is a func for add :")
        time.sleep(1)
        print("result is %d" %(a+b))
    
    
    
    if __name__ == '__main__':
        f = func
        f(3,4)
        #func()
    
    '''
    this is deco01
    this is deco02
    hello,here is a func for add :
    result is 7
    deco02 end here
    time is 1003 ms
    deco01 end here
    '''
    

    多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。

    盗用评论里面一位童鞋的例子:

    def dec1(func):  
        print("1111")  
        def one():  
            print("2222")  
            func()  
            print("3333")  
        return one  
      
    def dec2(func):  
        print("aaaa")  
        def two():  
            print("bbbb")  
            func()  
            print("cccc")  
        return two  
     
    @dec1  
    @dec2  
    def test():  
        print("test test")  
      
    test()  
    

    输出:

    aaaa  
    1111  
    2222  
    bbbb  
    test test  
    cccc  
    3333
    

    装饰器的外函数和内函数之间的语句是没有装饰到目标函数上的,而是在装载装饰器时的附加操作。

    17~20行是装载装饰器的过程,相当于执行了test=dect1(dect2(test)),此时先执行dect2(test),结果是输出aaaa、将func指向函数test、并返回函数two,然后执行dect1(two),结果是输出1111、将func指向函数two、并返回函数one,然后进行赋值。

    用函数替代了函数名test。 22行则是实际调用被装载的函数,这时实际上执行的是函数one,运行到func()时执行函数two,再运行到func()时执行未修饰的函数test。

    参考:Python 装饰器:http://python.jobbole.com/82344/

    这里写图片描述

    展开全文
  • Python 装饰器

    2021-01-20 03:16:28
    文章目录Python 装饰器一、装饰器定义二、装饰器知识储备三、高阶函数1.高阶函数定义:2.高阶函数的示范3.高阶函数的总结四、函数嵌套五、闭包 Python 装饰器 一、装饰器定义 装饰器本质就是函数,功能是为其他函数...
  • python 装饰器

    千次阅读 2017-06-04 00:04:47
    Python装饰器

    Python装饰器

    如果要增强某一函数的功能,但又不希望修改原函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。写代码需要遵循开放封闭原则,已经实现的功能代码不允许被修改,但可以被扩展

    例如要给func函数增加一功能,只需定义一个login装饰器即可

    def login(func):
        def inner(arg,arg1):
            print('login')
            return func(arg,arg1)
        return inner

    @login       #此次相当于执行了func=login(func)
    def func(arg,arg1):
        print('func: %s -- %s'%(arg,arg1))

    func('hello','world')

    运行结果:

    login

    func: hello -- world

     

    如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数


    def login(txt):
        def outer(func):
            def inner(arg,arg1):
                print(txt)
                return func(arg,arg1)
            return inner
        return outer

    @login('hehe') #装饰器带参数

    #第一步执行login('hehe')

    #第二步执行@outer(func)
    def func(arg,arg1):
        print('func: %s -- %s'%(arg,arg1))

    func('hello','world')

    运行结果:

    hehe

    func: hello -- world

    展开全文
  • python装饰器

    2020-12-23 02:00:30
    装饰器 装饰器的本质:一个闭包函数 装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展 import time def func1(): print('in func1') def timer(func): # 装饰器函数 def inner(): start = ...
  • python装饰器解释

    万次阅读 2020-05-01 15:51:21
    python装饰器python装饰器的简单解释装饰器详解(加了参数)python装饰器高级解释(直接上图) python装饰器的简单解释 python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加...

    python装饰器的简单解释

    python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。简单的说装饰器就是一个用来返回函数的函数。

    它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

    概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

    先看如下代码
    在这里插入图片描述
    写了@cal_time 会立马的调用函数
    现在我们在cal_time的外部函数输出一句话

    在这里插入图片描述
    控制台输出结果
    在这里插入图片描述

    调用demo函数的时候相当于调用 cal_time函数内部的inner,然后内部再调用fn指向外部的demo函数在这里插入图片描述

    装饰器详解(加了参数)

    只加一个参数的情况
    在写参数的时候特别注意(最根本的根本则是调用ca_time 内部的 inner函数,所以在内部的inner参数也需要加上)
    在这里插入图片描述
    现在是如果要加入多个参数
    在这里插入图片描述

    python装饰器高级解释(直接上图)

    这里有一个小细节 在取 kwargs的值时候,最好使用字典。
    避免没有传值的时候报错 。
    字典.get 如果 没有拿到值 就返回后面的默认值。
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Python装饰器-失败用例自动重试
  • Python装饰器

    千次阅读 2015-10-13 21:38:42
    python装饰器首先要明白的一点是,装饰器装饰的是函数。python之中为什么会有这样的需求?需求是怎么来的def foo(): print 'in foo()'foo()这是一个函数,如果需要对这个函数增加一些功能,比如需要计算这个函数...

    python装饰器

    首先要明白的一点是,装饰器装饰的是函数。python之中为什么会有这样的需求?

    需求是怎么来的

    def foo():
        print 'in foo()'
    
    foo()

    这是一个函数,如果需要对这个函数增加一些功能,比如需要计算这个函数运行所消耗的时间。

    import time
    def foo():
        start = time.clock()
        print 'in foo()'
        end = time.clock()
        print 'used:', end - start
    
    foo()

    如果其他函数也需要计算运行时间呢?复制代码?DRY,所以可以将计算函数运行时间的功能抽象出来。

    import time
    
    def foo():
        print 'in foo()'
    
    def timeit(func):
        start = time.clock()
        func()
        end =time.clock()
        print 'used:', end - start
    
    timeit(foo)

    嗯,看上去挺不错的。不过这里的弱点是修改了调用部分的代码,关键是有的时候如果调用的函数是库函数的话就麻烦了。

    所以这个时候想到的就是对foo进行包装,将timeit编写为对foo的包装函数,传入foo之后对foo进行加强,返回一个新的foo。

    #-*- coding: UTF-8 -*-
    import time
    
    def foo():
        print 'in foo()'
    
    # 定义一个计时器,传入一个函数,并返回另一个附加了计时功能的函数
    def timeit(func):
        # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
        def wrapper():
            start = time.clock()
            func()
            end =time.clock()
            print 'used:', end - start
        # 将包装后的函数返回
        return wrapper
    
    foo = timeit(foo)
    foo()

    PS:在在这个例子中,函数进入和退出时需要计时,这被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。与传统编程习惯的从上往下执行方式相比较而言,像是在函数执行的流程中横向地插入了一段逻辑。在特定的业务领域里,能减少大量重复代码。

    问题:如果foo带参数怎么办?
    很简单,装饰器之中的包装函数的参数和被装饰的函数的参数需要统一。

    def deco(func):
        def _deco(a, b):
            print("before myfunc() called.")
            ret = func(a, b)
            print("  after myfunc() called. result: %s" % ret)
            return ret
        return _deco
    
    @deco
    def myfunc(a, b):
        print(" myfunc(%s,%s) called." % (a, b))
        return a + b

    再举一个例子是Django之中的Signal装饰器:

    def receiver(signal, **kwargs):
        def _decorator(func):
            if isinstance(signal, (list, tuple)):
                for s in signal:
                    s.connect(func, **kwargs)
            else:
                signal.connect(func, **kwargs)
            return func
        return _decorator

    语法糖

    Python对装饰器提供了语法糖:

    import time
    
    def timeit(func):
        def wrapper():
            start = time.clock()
            func()
            end =time.clock()
            print 'used:', end - start
        return wrapper
    
    @timeit
    def foo():
        print 'in foo()'
    
    foo()

    内置装饰器

    内置的装饰器有三个,分别是staticmethod、classmethod和property。作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。

    class Rabbit(object):
    
        def __init__(self, name):
            self._name = name
    
        @staticmethod
        def newRabbit(name):
            return Rabbit(name)
    
        @classmethod
        def newRabbit2(cls):
            return Rabbit('')
    
        @property
        def name(self):
            return self._name

    示例比较简单,其中的函数是可以进行扩展的。这里@property定义的是一个只读属性,如果需要可写,则需要再一定一个setter:

    @name.setter
    def name(self,name):
        self._name = name
    展开全文
  • 如果作为一个Python入门,不了解Python装饰器也没什么,但是如果作为一个中级Python开发人员,如果再不对python装饰器熟稔于心的话,那么可能并没有量变积累到质变。 我以前也看过很多讲python 装饰器的文章,但是都...
  • Python装饰器(你想知道的这里都有)

    万次阅读 多人点赞 2020-09-25 10:47:57
    1. 装饰器的定义 就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。 装饰器的功能特点: 不修改已有函数的源代码 不修改已有函数的调用方式 给已有函数增加额外的功能 闭包和装饰器的区分: 如果闭包...
  • 21-Python 装饰器

    万次阅读 多人点赞 2020-10-26 08:08:00
    简明python 装饰器介绍简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 88,133
精华内容 35,253
关键字:

python装饰器

python 订阅