Python装饰器decorator用法实例


Posted in Python onNovember 10, 2014

本文实例讲述了Python装饰器decorator用法。分享给大家供大家参考。具体分析如下:

1. 闭包(closure)

闭包是Python所支持的一种特性,它让在非global scope定义的函数可以引用其外围空间中的变量,这些外围空间中被引用的变量叫做这个函数的环境变量。环境变量和这个非全局函数一起构成了闭包。

def outer(x):

    y = [1,2,3]

    def inner():

        print x

        print y

    return inner

x = 5    #这个x没有被引用

f = outer(2)

f()

print f.__closure__   #函数属性__closure__存储了函数的环境变量 def entrance(func):
 = 5    #这个x没有被引用f = outer(2)f()print f.__closure__   #函数属性__closure__存储了函数的环境变量 def entrance(func):
x和y都是属于函数outer命名空间的,在inner中被引用,当outer函数退出后,outer的命名空间不存在了,但是inner依然维护了其定义时候对其外部变量x,y的连接。
程序输出:

2

[1, 2, 3]

(, )

装饰器是一个可调用对象(a callable),在Python中,函数是对象,当然也是可调用的,所以装饰器可以是一个函数,我们称其为函数装饰器。
这个可调用对象以一个函数作为参数,闭且返回另一个函数(来替换参数那个函数)。
比如:

def entrance(func):

     def inner():

         print "inside function :", func.__name__

         func()

     return inner

 
entrance是一个装饰器,它是一个函数,它可以接收一个函数func作为参数,返回了另一个函数inner。
那为什么叫装饰器了,在返回函数inner()的内部,调用了func(),而且还作了额外的操作,相当于“装饰”了函数func。
那如何使用装饰器?
def fun1():

    pass

fun1 = entrance(fun1)

def fun2():

    pass

fun2 = entrance(fun2)

 
fun1,fun2的名字都没有变,但是通过调用函数装饰器entrance(),它们已经指向了另一个函数inner(),“装饰了”自己。

@操作符

Python提供的@符号,实质上就是上面做的,对一个函数名进行从新赋值,是语法上的技巧。所以上面的代码等价于

@entrance

def fun1():

    pass

@entrance

def fun2():

    pass

 
2. 装饰器的用途

从这个刻意构造的很简单的例子,可以看出装饰器的意义,如果一个函数需要一个功能,如果这个功能可以被使用在很多函数上,或是函数并不是自己实现,那可以写个装饰器来实现这些功能。
上面的装饰器entrance,装饰一个函数后,函数被调用时会打印出这个函数的名字。
但是有一个问题,这个装饰器从功能上看,是要应该可以用来装饰任何函数,但是如果我们用它来装饰了一个带参数的函数

@entrance

 def fun3(x):

     pass

只要不调用fun3,这三行代码是不会让Python解释器报错的,因为我们已经知道,它等价于:
def fun3(x):

    pass

fun3 = entrance(fun3)

 
我们定义了一个带参的函数fun3,然后把fun3指向了另一个函数inner(),当然不会有什么错。
 
但是,当我们使用fun3时,我们肯定会按照它定义时的样子去使用它,给它传入一个参数。
>>>fun3(1)
这里就会出错了,看看解释器怎么报错的

Traceback (most recent call last):
File “decorator.py”, line 23, in 3water.com <module>
fun3(1)
TypeError: inner() takes no arguments (1 given)

当然我们已经很容易知到为什么会这样报错了,fun3已经不是指向它定义时那个函数了,它现在指向了”inner()”,而inner是没有参数的,当然会出错。
那怎么解决呢?
修改一下inner()的定义,让它可以就收任意个参数就可以了。

def entrance(func):

     def inner(*args, **kvargs):

         print "inside function : ", func.__name__

         func(*args, **kvargs)

     return inner

现在,给inner传任意个参数都不会出错了,也就是entrance可以被用来装饰任何一个函数了。

3. 写个装饰器logger

一个函数被调用时,在日志里记录其名称和被调用的实际参数

def logger(func):

    def inner(*args, **kvargs):

        print  func.__name__, 'called, arguments: ', args, kvargs

        func(*args, **kvargs)

    return inner

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
python学习之面向对象【入门初级篇】
Jan 21 Python
Python轻量级ORM框架Peewee访问sqlite数据库的方法详解
Jul 20 Python
Python字符串的常见操作实例小结
Apr 08 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
Aug 10 Python
Python爬虫:将headers请求头字符串转为字典的方法
Aug 21 Python
Python循环实现n的全排列功能
Sep 16 Python
python安装gdal的两种方法
Oct 29 Python
在Python中使用filter去除列表中值为假及空字符串的例子
Nov 18 Python
python3实现绘制二维点图
Dec 04 Python
Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]和X[:,:,m:n]
Feb 13 Python
python 实现rolling和apply函数的向下取值操作
Jun 08 Python
scrapy-splash简单使用详解
Feb 21 Python
python中list循环语句用法实例
Nov 10 #Python
python中MySQLdb模块用法实例
Nov 10 #Python
Python实现子类调用父类的方法
Nov 10 #Python
Python模仿POST提交HTTP数据及使用Cookie值的方法
Nov 10 #Python
Python类的多重继承问题深入分析
Nov 09 #Python
python查询mysql中文乱码问题
Nov 09 #Python
python刷投票的脚本实现代码
Nov 08 #Python
You might like
关于PHP实现异步操作的研究
2013/02/03 PHP
destoon实现首页显示供应、企业、资讯条数的方法
2014/07/15 PHP
php版微信公众号接口实现发红包的方法
2016/10/14 PHP
laravel框架与其他框架的详细对比
2019/10/23 PHP
jquery中通过过滤器获取表单元素的实现代码
2011/07/05 Javascript
Prototype源码浅析 String部分(三)之HTML字符串处理
2012/01/15 Javascript
使用JavaScript 实现各种跨域的方法
2013/05/08 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
纯js实现无限空间大小的本地存储
2015/06/18 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
原生js实现图片轮播特效
2015/12/18 Javascript
js实现各浏览器全屏代码实例
2018/07/03 Javascript
Angularjs实现页面模板清除的方法
2018/07/20 Javascript
element-ui的回调函数Events的用法详解
2018/10/16 Javascript
vue 指令之气泡提示效果的实现代码
2018/10/18 Javascript
详解webpack打包后如何调试的方法步骤
2018/11/07 Javascript
Vue.js下拉菜单组件使用方法详解
2019/10/19 Javascript
vue路由 遍历生成复数router-link的例子
2019/10/30 Javascript
微信小程序实现拨打电话功能的示例代码
2020/06/28 Javascript
python实现的文件夹清理程序分享
2014/11/22 Python
python好玩的项目—色情图片识别代码分享
2017/11/07 Python
python安装教程
2018/02/28 Python
使用jupyter notebook直接打开.md格式的文件
2020/04/10 Python
详细分析Python垃圾回收机制
2020/07/01 Python
纯DOM+CSS3实现简单的小风车动画
2016/09/27 HTML / CSS
HTML5+css3:3D旋转木马效果相册
2017/01/03 HTML / CSS
html5响应式开发自动计算fontSize的方法
2020/01/13 HTML / CSS
美国性感女装网站:bebe
2017/03/04 全球购物
大学生学习党课思想汇报
2014/01/03 职场文书
六十大寿答谢词
2014/01/12 职场文书
拉拉队口号
2014/06/16 职场文书
2015年高校就业工作总结
2015/05/04 职场文书
悬崖上的金鱼姬观后感
2015/06/15 职场文书
2015年新农村建设指导员工作总结
2015/07/24 职场文书
2016同学毕业寄语大全
2015/12/04 职场文书
如何利用python和DOS获取wifi密码
2021/03/31 Python