python中的装饰器

来源:互联网 发布:天刀神威女捏脸数据 编辑:程序博客网 时间:2024/05/16 17:12

Python中的装饰器可以很方便的对已有的函数进行改写或者优化,从某种程度上可以将函数看成类,装饰器的作用就是类继承的过程。

def log(func):    def wrapper(*arg,**kw):        print('call %s' % func.__name__)        return func(*arg,**kw)    return wrapper@logdef now():    print('2017-1-7')now()

运行的结果是:

call now2017-1-7

代码中的@语法相当于now=log(now)。我们可以将上面的代码写成下面的形式:

def log(func):    def wrapper(*arg,**kw):        print('call %s' % func.__name__)        return func(*arg,**kw)    return wrapperdef now():    print('2017-1-7')log(now)()

结果依然是:

call now2017-1-7

从上面两段代码可以看出@xxx的作用等价于now=xxx(now),也就是log是一个将紧跟他下面的函数作为参数的函数。无论函数xxx里有多少层函数,跟在@后面的函数或其所指向的函数必须是以函数作为参数的。我们来看下面一段代码:

def log(text):    if isinstance(text,str):        def decorator(func):            def wrapper(*args, **kw):                print('%s %s():' % (text, func.__name__))                return func(*args, **kw)            return wrapper        return decorator    else:        def wrapper(*args, **kw):            print('call %s()' % text.__name__)            return text(*args, **kw)        return wrapper        @logdef now1():    print('2017-1-7')@log('excute')def now2():    print('2017-1-7')now1()now2()

运行结果如下:

call now()2017-1-7excute now():2017-1-7

上面的这段代码中的装饰器,除了正常的功能外,还可以加参数,这是为什么呢?在函数log中,先判断的是参数text的类型,先不论text是那种类型,函数log或其所指向的函数必须都是以函数作为参数的。@log的作用等价于now1=log(now1)now1是函数类型,不是字符串类型,所以执行的是这段代码:

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

@xxxxxx就是一个函数,因此@log('excute')log('excute')就是一个函数,所以log('excute')的作用等价于now2=log('excute')(now2)。但是,'excute'先传进去的所以经判断执行的是这段代码:

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

在这还有最后一个问题就是now__name__属性会变成wrapper,还是因为now2=log('excute')(now2)log('excute')(now2)指向的函数就是wrapper,因此完整的代码就是:

import functoolsdef log(text):    if isinstance(text,str):        def decorator(func):            @functools.wraps(func)            def wrapper(*args, **kw):                print('%s %s():' % (text, func.__name__))                return func(*args, **kw)            return wrapper        return decorator    else:        @functools.wraps(text)        def wrapper(*args, **kw):            print('call %s()' % text.__name__)            return text(*args, **kw)        return wrapper        @logdef now1():    print('2017-1-7')@log('excute')def now2():    print('2017-1-7')now1()now2()

@functools.wraps(func)的作用就是wrapper.__name__ = func.__name__

0 0
原创粉丝点击