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网络编程学习笔记(三):socket网络服务器
Jun 09 Python
python实现查询IP地址所在地
Mar 29 Python
Linux下将Python的Django项目部署到Apache服务器
Dec 24 Python
在python中使用正则表达式查找可嵌套字符串组
Oct 24 Python
详解python上传文件和字符到PHP服务器
Nov 24 Python
详解python OpenCV学习笔记之直方图均衡化
Feb 08 Python
jupyter notebook 中输出pyecharts图实例
Apr 23 Python
如何使用Flask-Migrate拓展数据库表结构
Jul 24 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
Feb 24 Python
python GUI库图形界面开发之PyQt5时间控件QTimer详细使用方法与实例
Feb 26 Python
anaconda python3.8安装后降级
Jun 11 Python
端午节将至,用Python爬取粽子数据并可视化,看看网友喜欢哪种粽子吧!
Jun 11 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
探讨:parse url解析URL,返回其组成部分
2013/06/14 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
2018/09/05 PHP
用JavaScript脚本实现Web页面信息交互
2006/10/11 Javascript
JavaScript入门教程(3) js面向对象
2009/01/31 Javascript
JavaScript 权威指南(第四版) 读书笔记
2009/08/11 Javascript
JS 添加网页桌面快捷方式的代码详细整理
2012/12/27 Javascript
JavaScript不刷新实现浏览器的前进后退功能
2014/11/05 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
javascript针对cookie的基本操作实例详解
2015/11/30 Javascript
json定义及jquery操作json的方法
2016/09/29 Javascript
JS实现自动阅读单词(有道单词本添加功能)
2016/11/14 Javascript
JS中关于事件处理函数名后面是否带括号的问题
2016/11/16 Javascript
JavaScript实现Fly Bird小游戏
2016/12/15 Javascript
html中通过JS获取JSON数据并加载的方法
2017/11/30 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
微信小程序实现两边小中间大的轮播效果的示例代码
2018/12/07 Javascript
小程序显示弹窗时禁止下层的内容滚动实现方法
2019/03/20 Javascript
在vue中使用防抖函数组件操作
2020/07/26 Javascript
基于python select.select模块通信的实例讲解
2017/09/21 Python
Numpy数据类型转换astype,dtype的方法
2018/06/09 Python
使用Python实现一个栈判断括号是否平衡
2018/08/23 Python
Python简单处理坐标排序问题示例
2019/07/11 Python
Python实现在Windows平台修改文件属性
2020/03/05 Python
Python3实现飞机大战游戏
2020/04/24 Python
Django 实现 Websocket 广播、点对点发送消息的代码
2020/06/03 Python
HTML5和以前HTML4的区别整理
2013/10/20 HTML / CSS
Sunglasses Shop德国站:欧洲排名第一的太阳镜网站
2017/08/01 全球购物
最经典的大学生职业生涯规划范文
2014/03/05 职场文书
2014班子“三严三实”对照检查材料思想汇报
2014/09/18 职场文书
党员干部公开承诺书范文
2015/04/27 职场文书
政审证明范文
2015/06/19 职场文书
文艺演出主持词
2015/07/01 职场文书
新手入门Mysql--概念
2021/06/18 MySQL
通过T-SQL语句创建游标与实现数据库加解密功能
2022/03/16 SQL Server
Python可视化动图组件ipyvizzu绘制惊艳的可视化动图
2022/04/21 Python
win7配置本地ftp服务器的图文教程
2022/08/05 Servers