zoukankan      html  css  js  c++  java
  • python 装饰器

    函数是一个引用类型,函数对象可以被赋予给变量,然后通过变量调用:

    函数对象有一个__name__属性,可以获得函数的名字:

    如果我们现在要增强now()函数的功能(比如在执行now函数前打印日志),但是又不想修改now()函数,在代码运行期间动态增加功能的方式,叫做装饰器。

    本质上,装饰器(decorator)就是一个"返回值是一个函数"的高阶函数,满足打印日志的装饰器示例如下:

    def log(func):
        def wrapper(*args, **kw):
            print 'call %s():' % func.__name__
            return func(*args, **kw)
        return wrapper

    上面的装饰器接收一个函数作为参数,并返回一个函数,我们使用@语法,把decorator置于函数定义处:

    @log

    def now():

        print '20160831'

    调用函数now,执行如下:

    把@log放到now()函数的定义处,相当于执行了语句:

    now = log(now)

    也就是now变量重新进行了赋值,返回值是wrapper函数,先打印日志,然后再调用原始函数。

    如果装饰器本身需要传入参数,那就需要编写一个返回装饰器的高阶函数,如下:

    def log(text):
        def decorator(func):
            def wrapper(*args, **kw):
                print '%s %s():' % (text, func.__name__)
                return func(*args, **kw)
            return wrapper
        return decorator

    这个三层嵌套的装饰器用法如下:

    @log('execute')
    def now():
        print '2013-12-25'

    执行结果如下:

    >>> now()
    execute now():
    2013-12-25  

    三层嵌套相当于执行

    >>> now = log('execute')(now)

    首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数。

    decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper'

    >>> now.__name__
    'wrapper'   

    因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。
    使用Python内置的functools.wraps,完整的装饰器如下:

    import functools

    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print 'call %s():' % func.__name__
            return func(*args, **kw)
        return wrapper

    或者带参数的装饰器:

    import functools

    def log(text):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print '%s %s():' % (text, func.__name__)
                return func(*args, **kw)
            return wrapper
        return decorator 

      

  • 相关阅读:
    Linux命令格式
    Android SDK Manager下载,解决方案
    北大校长王恩哥送给毕业学生的十句话
    Andorid API Package ---> android.app
    Andorid API Package --->android.animation
    Andorid API Package ---> android.accessibilityservice
    Andorid API Package ---> android
    计算机经典书籍列表
    Ubuntu 10.04 下载android 4.1.1_r4
    canvas绘画基础(一):认识canvas画布
  • 原文地址:https://www.cnblogs.com/zhaojonjon/p/5825439.html
Copyright © 2011-2022 走看看