Python中的装饰器(Decorator)

# 注:本文参考廖雪峰老师的博客

所谓装饰器(Decorator)就是一个返回函数的高阶函数,它可以在运行期间动态的增加函数的功能。

首先看一个简单的例子:

>>> def now():
    print '2015-05-12'
>>> 
>>> now()
2015-05-12

现在我想增加一些功能,但又不想改变原来函数。我们就可以使用装饰器。

>>> def log(func):
    def wrapper(*args, **kw):
        print 'call %s():' % func.__name__
        return func(*args, **kw)
    return wrapper
>>> @log
def now():
    print '2015-05-12'
>>> now()
call now():
2015-05-12

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

now = log(now)

由于log是一个decorator,会返回一个函数,即log(now)返回了wrapper()函数。所以原来的now()函数会指向一个新的函数,即wrapper()。

而wrapper()函数又返回了原来的now()函数,并打印出指定的信息。

>>> now.__name__
'wrapper'
可以看出,now()函数现在指向的是wrapper()函数了。


若装饰器想带参数,就要加多一层嵌套了。

>>> def log(text):
    def decorotar(func):
        def wrapper(*args, **kw):
            print '%s function %s():' % (text, func.__name__)
            return func(*args, **kw)
        return wrapper
    return decorotar
>>> 
>>> @log('execute')
... def now():
...     print '2015-05-12'
...     
>>> now()
execute function now():
2015-05-12
带了参数后的装饰器相当于执行log('execute')(now),即:首先执行的是log('execute'),返回decorator函数,

即一个没带参数的装饰器,然后再执行decorator(now)返回wrapper(),最后返回传入的now()函数。

这里函数的名称还是wrapper

>>> now.__name__
'wrapper'

但,这样跟我们原来设想的就会有出入了。因为,我们认为__name__这个属性返回的应该是我们原本调用的函数名称,即:now

而,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
...     
>>> @log
... def now():
...     print '2015-05-12'
...     
>>> now.__name__
'now'

带参数的装饰器:

>>> import functools
>>> def log(text):
...     def decorator(func):
...         @functools.wraps(func)
...         def wrapper(*args, **kw):
...             print '%s function %s():' % (text, func.__name__)
...             return func(*args, **kw)
...         return wrapper
...     return decorator
...     
>>> @log('execute')
... def now():
...     print '2015-05-12'
...     
>>> now.__name__
'now'
>>> now()
execute function now():
2015-05-12


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值