为了账号安全,请及时绑定邮箱和手机立即绑定

Python 装饰器浅析

标签:
Python

Python 装饰器是 Python 中常常使用到的一种语法糖,它可以大幅度减少重复代码,使用起来十分方便。另一方面,装饰器的定义往往会导致出现函数重重嵌套的情况,这会给装饰器的实现者带来阅读代码的困难。

本文剖析 Python 装饰器的定义与用法。

不带参数的装饰器

我们先来看一下不带参数的装饰器的实现,这种情况比较简单。以下是一个不带参数的装饰器的使用例子:

@decoratordef fun():
    print('fun() is called')

前面提到,装饰器只是 Python 提供的语法糖,使用@decorator作为装饰器相当于:

def fun():
    print('fun() is called')
fun = decorator(fun)

我们再来看一下装饰器decorator本身的定义。装饰器可以使用函数实现,也可以使用类来实现,这里我们介绍函数的实现方式。

def decorator(fun):
    def decorated_function():
        print('before fun, do something')
        fun()
        print('after fun, do something')    return decorated_function

装饰器decorator被定义成一个函数,这个函数返回一个新的函数。同时,我们看到decorator接受一个fun的形参,fun作为一个函数,会在decorated_function中被调用。

使用装饰器后,如果调用fun(),则会输出:

before fun, do something
 fun() is called
 after fun, do something

通过装饰器decorator,原来的fun函数,被赋值成decorator(fun),而decorator(fun)会触发decorator函数的调用并返回decorated_function这个函数。在decorated_function中,会先输出before fun, do something,然后调用fun(),最后输出after fun, do something

带参数的装饰器

装饰器支持带参数,我们先来看下带参数的装饰器的使用方式。

@cached(5)def fun():
    print('fun() is called')

上面带参数的装饰器的使用,等价于以下的代码:

def fun():
    print('fun() is called')
fun = cached(5)(fun)

装饰器cached被定义成一个函数,它的定义如下:

def cached(timeout):
    def decorator(func):
        def decorated_function():
            print('before fun, do something, timeout=%d' % timeout)
            func()
            print('after fun, do something, timeout=%d' % timeout)        return decorated_function    return decorator

cached是一个函数,它接受一个timeout的形参,并返回一个decorator的函数。cached(5)会进行函数调用且函数的实参为5,并返回decoratordecorator也是个函数,decorator(fun)(即cached(5)(fun))相当于上面不带参数的装饰器的使用,它返回decorated_function这个函数。
看起来有点复杂,实际上,带参数的装饰器只是在不参数的装饰器的基础上再多一层函数的封装而已,多的这层函数是为了将装饰器的参数传递进去。

使用装饰器后,如果调用fun()函数,则会输出:

before fun, do something, timeout=5
 fun() is called
 after fun, do something, timeout=5

参考资料

  1. http://www.lightxue.com/understand-python-decorator-the-easy-way

  2. https://mp.weixin.qq.com/s/98JA68TX9X4j6wPABiMJNA

  3. https://mp.weixin.qq.com/s/Om98PpncG52Ba1ZQ8NIjLA

  4. http://code.oneapm.com/python/2015/04/27/python-decorator-mistake/

  5. http://www.jianshu.com/p/d03e4dfc5a78

  6. http://blog.guoyb.com/2016/04/19/python-decorator/

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消