简单上手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 14 Python
python中使用smtplib和email模块发送邮件实例
Apr 22 Python
关于numpy中np.nonzero()函数用法的详解
Feb 07 Python
python的mysqldb安装步骤详解
Aug 14 Python
python使用正则表达式替换匹配成功的组
Nov 17 Python
对python中使用requests模块参数编码的不同处理方法
May 18 Python
python变量命名的7条建议
Jul 04 Python
获取Pytorch中间某一层权重或者特征的例子
Aug 17 Python
使用pytorch搭建AlexNet操作(微调预训练模型及手动搭建)
Jan 18 Python
python IDLE添加行号显示教程
Apr 25 Python
如何在VSCode下使用Jupyter的教程详解
Jul 13 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
Aug 04 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
在字符串指定位置插入一段字符串的php代码
2010/02/16 PHP
php递归删除目录下的文件但保留的实例分享
2014/05/10 PHP
PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
2014/07/23 PHP
浅析PHP编程中10个最常见的错误
2014/08/08 PHP
PHP获取远程图片并保存到本地的方法
2015/05/12 PHP
Yii框架中sphinx索引配置方法解析
2016/10/18 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
javascript判断iphone/android手机横竖屏模式的函数
2011/12/20 Javascript
基于KMP算法JavaScript的实现方法分析
2013/05/03 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
2014/04/11 Javascript
利用js制作html table分页示例(js实现分页)
2014/04/25 Javascript
AngularJS 日期格式化详解
2015/12/23 Javascript
jQuery插件之Tocify动态节点目录菜单生成器附源码下载
2016/01/08 Javascript
使用JavaScript实现ajax的实例代码
2016/05/11 Javascript
jQuery事件处理的特征(事件命名机制)
2016/08/23 Javascript
全屏滚动插件fullPage.js使用实例解析
2016/10/21 Javascript
基于js中的原型(全面讲解)
2017/09/19 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
微信小程序自定义弹窗滚动与页面滚动冲突的解决方法
2019/07/16 Javascript
微信小程序实现watch监听
2020/06/04 Javascript
JavaScript十大取整方法实例教程
2020/12/03 Javascript
python实现的简单FTP上传下载文件实例
2015/06/30 Python
Python中的条件判断语句基础学习教程
2016/02/07 Python
Python面向对象程序设计多继承和多态用法示例
2019/04/08 Python
详解爬虫被封的问题
2019/04/23 Python
Pyqt5 基本界面组件之inputDialog的使用
2019/06/25 Python
Python 使用生成器代替线程的方法
2020/08/04 Python
使用phonegap播放音频的实现方法
2017/03/31 HTML / CSS
洲际酒店集团英国官网:IHG英国
2019/07/10 全球购物
办公室文秘岗位职责
2013/11/15 职场文书
先进事迹报告会感言
2014/01/24 职场文书
建筑工程技术专业求职信
2014/07/16 职场文书
创先争优演讲稿
2014/09/15 职场文书
党员个人总结自评
2015/02/14 职场文书
保送生自荐信范文
2015/03/26 职场文书
React实现动效弹窗组件
2021/06/21 Javascript