对Python装饰器的个人理解方法
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:函数和函数式编程》

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
烂泥:利用awstats分析nginx日志
昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看《烂泥:切割nginx日志》这篇文章。 今天打算分析下nginx日志,要分析nginx日志,我们可以通过shell脚本和第三方软件awstats进行分析,在此我们选择的是通过第三方软件awstats进行分析。 要使用awstats分析nginx日志,我们要安装awstats,而在安装awstats之前,我们需要先来介绍下awstats是什么? 一、awstats是什么 awstats是一个免费非常简洁而且强大有个性的基于Perl语言的WEB日志分析工具。 它可以统计网站的如下信息: 1):访问量、访问次数、页面浏览量、点击数、数据流量等。 2):精确到每月、每日、每小时的数据。 3):访问者国家以及IP。 4):Robots/Spiders的统计。 5):访客持续时间。 6):对不同files type的统计信息。 7):Pages-URL的统计。 8):访客操作系统浏览器等信息。 9):其它信息(搜索关键字等等) 二、准备工作 在介绍完awstats是什么之后,我们再来介绍下安装awstats之前的准备工作。 ...
- 下一篇
Centos 7 DNS配置及理论详解
DNS是什么及BIND讲解内容 域名系统(英文:Domain Name System,缩写:DNS)是internet的一项服务。它作为将域名和IP地址相互映射服务,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。讲解内容: DNS名称解析方式 DNS查询类型 DNS服务器类型 区域数据库文件详解 Centos7安装配置BIND BIND主从服务器配置 BIND安全相关配置 BIND view视图配置 一、DNS名称解析方式 DNS名称解析方式分为两种: 名称 ---> IP 例如:此处命令会在后面工具中具体详解 # 可以看出“名称”www.magedu.com对应的ip是101.200.188.230 #dig-tAwww.magedu.com ;<<>>DiG9.9.4-RedHat-9.9.4-29.el7<<>>-tAwww.magedu.com ;;globaloptions:+cmd ;;Gotansw...
相关文章
文章评论
共有0条评论来说两句吧...