简单上手Python中装饰器的使用


Posted in Python onJuly 12, 2015

Python的装饰器可以实现在代码运行期间修改函数的上下文, 即可以定义函数在执行之前进行何种操作和函数执行后进行何种操作, 而函数本身并没有任何的改变。

这个看起来很复杂, 实际上应用到了我之前说过的闭包的概念, 仔细看一看, 其实并不复杂。

首先, 我们先定义一个函数, 这个函数可以输出我的个人昵称:

def my_name():
  print "Yi_Zhi_Yu"
my_name() # Yi_Zhi_Yu

那假如我需要在个人昵称输出前, 在输出我的个人uid呢, 当然, 要求是不改动现有的my_name函数, 这个时候就可以使用装饰器了

首先, 装饰器也是个函数, 其次, 他需要接受一个参数,该参数表示了要被装饰的函数(即my_name):

def my_info(func):
  def wrapper(*args, **params):
    print 218
    return func(*args, **params)
  return wrapper

然后与相应的被装饰函数关联起来的方法就是使用@my_info写在被装饰函数的前面

@my_info
def my_name():
  print "Yi_Zhi_Yu"

最后, 在执行my_name的时候, 就能既输出我的uid, 又能输出我的昵称了

my_name()
#218
#Yi_Zhi_Yu

在上面, 最让我们疑惑的是装饰器函数定义里面的wrapper函数, 装饰器本身返回的是wrapper函数的定义, 而wrapper中则定义了对被装饰函数(my_name)的调用, func表示的就是被装饰函数, 说白了, 装饰器只是把某个不得改动的函数(a)放到另一个函数(b)中, 在b里面调用a, 在调用前后就可以做所谓的看起来像装饰的工作了。
my_info的最终返回的wrapper函数的定义, 并不是执行结果,只有当wrapper真正执行的时候, 才会真正的执行my_name方法, 这就是闭包时所说的内容。
wrapper中的参数, 实际上则是传递给func(实际上是my_name)的参数

因为装饰器也是个函数, 那么装饰器自己的能不能有参数传递呢。可以, 不过需要定义一个更高阶的函数, 也就是外面还要套一层函数, 比如, 我还要输出我的自定义的一个信息,需要传递参数

def c_info(text):
  def my_info(func):
    def wrapper(*args, **params):
      print text
      print 218
      return func(*args, **params)
    return wrapper
  return my_info

 #使用装饰器
 @c_info("Tony")
 def my_name():
  print "Yi_Zhi_Yu"

 my_name()
 #Tony
 #218
 #Yi_Zhi_Yu

与前面的那个装饰器相比, 仅仅是多了个外层, 内层也仅仅是增加了对外层传入参数(text)的调用

总而言之, Python在函数定义中支持了对oop思想中的装饰器的实现, 其本质也只是使用了闭包的思路, 延迟调用, 并在调用前后增加自己的其他实现内容

Python 相关文章推荐
Python使用设计模式中的责任链模式与迭代器模式的示例
Mar 02 Python
利用Python如何生成随机密码
Apr 20 Python
python决策树之C4.5算法详解
Dec 20 Python
Django视图和URL配置详解
Jan 31 Python
python数据封装json格式数据
Mar 04 Python
详解python实现识别手写MNIST数字集的程序
Aug 03 Python
浅析python中numpy包中的argsort函数的使用
Aug 30 Python
Django CBV类的用法详解
Jul 26 Python
使用Python测试Ping主机IP和某端口是否开放的实例
Dec 17 Python
python GUI库图形界面开发之PyQt5信号与槽基础使用方法与实例
Mar 06 Python
Python判断变量是否是None写法代码实例
Oct 09 Python
基于Python实现的购物商城管理系统
Apr 27 Python
python比较两个列表大小的方法
Jul 11 #Python
python实现计算倒数的方法
Jul 11 #Python
python实现基本进制转换的方法
Jul 11 #Python
python计算圆周率pi的方法
Jul 11 #Python
python计算一个序列的平均值的方法
Jul 11 #Python
python修改字典内key对应值的方法
Jul 11 #Python
python字典基本操作实例分析
Jul 11 #Python
You might like
ftp类(myftp.php)
2006/10/09 PHP
一个程序下载的管理程序(二)
2006/10/09 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
表格展示无限级分类(PHP版)
2012/08/21 PHP
ThinkPHP3.1基础知识快速入门
2014/06/19 PHP
php中运用http调用的GET和POST方法示例
2014/09/29 PHP
简单谈谈favicon
2015/06/10 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
使用jQuery实现的网页版的个人简历(可换肤)
2013/04/19 Javascript
javascript使用正则表达式检测IP地址
2014/12/03 Javascript
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
2015/03/31 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
基于JavaScript实现添加到购物车效果附源码下载
2016/08/22 Javascript
浅谈Angular中ngModel的$render
2016/10/24 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
2017/04/25 jQuery
3分钟读懂移动端rem使用方法(推荐)
2019/05/06 Javascript
Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign)
2019/11/21 Javascript
webpack安装配置与常见使用过程详解(结合vue)
2020/06/01 Javascript
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
vue 表单输入框不支持focus及blur事件的解决方案
2020/11/17 Vue.js
python使用wxPython打开并播放wav文件的方法
2015/04/24 Python
python中利用xml.dom模块解析xml的方法教程
2017/05/24 Python
Python实现爬取需要登录的网站完整示例
2017/08/19 Python
Python内置模块hashlib、hmac与uuid用法分析
2018/02/12 Python
详解pycharm2020.1.1专业版安装指南(推荐)
2020/08/07 Python
Html5游戏开发之乒乓Ping Pong游戏示例(三)
2013/01/21 HTML / CSS
Vivo俄罗斯官方在线商店:中国智能手机品牌
2019/10/04 全球购物
乌克兰在线电子产品商店:MTA
2019/11/14 全球购物
公路绿化方案
2014/05/12 职场文书
八一建军节营销活动方案
2014/08/31 职场文书
支行行长岗位职责
2015/02/15 职场文书
2015年迎新晚会策划书
2015/07/16 职场文书
java objectUtils 使用可能会出现的问题
2022/02/28 Java/Android
《战锤40K:暗潮》跳票至9月 公布新宣传片
2022/04/03 其他游戏
代码复现python目标检测yolo3详解预测
2022/05/06 Python
mysql幻读详解实例以及解决办法
2022/06/16 MySQL