设为首页 收藏本站
查看: 3622|回复: 0

[经验分享] 对Python装饰器的个人理解方法

[复制链接]

尚未签到

发表于 2018-8-4 13:44:21 | 显示全部楼层 |阅读模式
  0.说明
  在自己好好总结并对Python装饰器的执行过程进行分解之前,对于装饰器虽然理解它的基本工作方式,但对于存在复杂参数的装饰器(装饰器和函数本身都有参数),总是会感到很模糊,即使这会弄懂了,下一次也很快忘记,其实本质上还是没有多花时间去搞懂其中的细节问题。
  虽然网络上已经有很多这样的文章,但显然都是别人的思想,因此自己总是记不牢,所以花点时间自己好好整理一下。
  最近在对《Python核心编程》做总结,收获了不少,下面分享一下我自己对于Python装饰器的理解,后面还提供了一个较为复杂的Python装饰器的执行过程的分解,可以参考一下。
  1.Python装饰器的出现
  在没有装饰器之前,如果要在类中定义一个静态方法,需要使用下面的方法:
class MyClass(object):  
    def staticFoo():
  
        staticFoo = staticmethod(staticFoo)
  即要在该静态方法中加入类似staticmethod()内建函数将该方法转换为静态方法,这显然非常麻烦,而有了装饰器之后,就可以写成下面这样:
class MyClass(object):  
    @staticmethod
  
    def staticFoo():
  
        pass
  这样就简洁很多了。
  2.Python装饰器类型与理解
  (1)无参数装饰器  

  •   一个装饰器
  下面的情况:
@f  
def foo():
  
    pass
  其实就相当于:
def foo():  
    pass
  
foo = g(foo)

  •   多个装饰器
  下面的情况:
@g  
@f
  
def foo():
  
    pass
  就相当于:
def foo():  
    pass
  
foo = g(f(foo))
  (2)含参数装饰器

  •   带有参数的一个装饰器
  下面的情况:
@decomaker(deco_args)  
def foo():
  
    pass
  就相当于:
def foo():  
    pass
  
foo = decomaker(deco_args)(foo)
  用这样的思想去理解就非常好理解了:decomaker()用deco_args做了些事并返回函数对象,而该函数对象正是以foo作为其参数的装饰器。
  下面多个装饰器的例子也是按这样的思想去理解。

  •   带有参数的多个装饰器
  下面的情况:
@deco1(deco_arg)  
@deco2()
  
def foo():
  
    pass
  就相当于:
def foo():  
    pass
  
foo = deco1(deco_arg)(deco2(foo))
  3.Python装饰器执行过程的手动分解
  OK,有了上面的理论基础,理解下面一个较为复杂的装饰器就很容易了:
from functools import wraps  

  
def log(text):
  
    def decorator(func):
  
        @wraps(func)                    #it works like:wraper.__name__ = func.__name__
  
        def wrapper(*args, **kwargs):
  
            print '%s %s():' % (text, func.__name__)
  
            return func(*args, **kwargs)
  
        return wrapper
  
    return decorator
  

  

  
@log('Hello')
  
def now(area):
  
    print area, '2016-01-23'
  

  

  
now('Beijing')
  
print 'The name of function now() is:', now.__name__
  执行如下:
/usr/bin/python2.7 /home/xpleaf/PycharmProjects/decorator_test/dec10.py  
Hello now():
  
Beijing 2016-01-23
  
The name of function now() is: now
  对于该程序的执行过程,可以分析如下:
  1.先执行log('Hello')函数,此时返回了一个新的函数,只不过其中的text变量被替换为'Hello',所以用来装饰now函数的新的装饰器如下:
def decorator(func):  
    @wraps(func)                    #it works like:wraper.__name__ = func.__name__
  
    def wrapper(*args, **kwargs):
  
        print '%s %s():' % ('Hello', func.__name__)
  
        return func(*args, **kwargs)
  
    return wrapper
  2.所以此时的now函数,就相当于:
now = decorator(now)  3.即now就相当于:
def now(*args, **kwargs):  
    print '%s %s():' % ('Hello', old_now.__name__)
  
    return old_now(*args, **kwargs)
  
# 现在的函数名称变为了now而不是wrapper,是因为使用了wraps装饰器
  所以,输出的结果也就非常好理解了。
  关于wraps,它也是一个装饰器,使用它的作用是,被我们用自定义装饰器修改后的函数,它的函数名称,即func.__name__跟原来是一样的,而它的工作原理正如上面所提及的,即:
wraper.__name__ = func.__name__  也就是说,使用wraps可以不改变原来函数的属性,当然,上面只是简单说明了一下其工作原理,详细的可以参考wraps的源代码。
  在GitHub上给出了10个理解装饰器的例子,可以参考一下:https://github.com/xpleaf/decorator
  本文选中我的《Python回顾与整理》系列博文中的《Python回顾与整理9:函数和函数式编程》

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-546537-1-1.html 上篇帖子: python打开大文件整理 下篇帖子: /usr/bin/python^M: bad interpreter: No such file
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表