python中的装饰器

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

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

@log
def now():
    print('2017-1-7')

now()

运行的结果是:

call now
2017-1-7

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

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

def now():
    print('2017-1-7')

log(now)()

结果依然是:

call now
2017-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        

@log
def now1():
    print('2017-1-7')

@log('excute')
def now2():
    print('2017-1-7')

now1()
now2()

运行结果如下:

call now()
2017-1-7
excute 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 functools

def 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        

@log
def now1():
    print('2017-1-7')

@log('excute')
def now2():
    print('2017-1-7')

now1()
now2()

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值