简单上手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入门学习之字符串与比较运算符
Oct 12 Python
如何处理Python3.4 使用pymssql 乱码问题
Jan 08 Python
解决Python中字符串和数字拼接报错的方法
Oct 23 Python
python Opencv将图片转为字符画
Feb 19 Python
Python实现压缩文件夹与解压缩zip文件的方法
Sep 01 Python
python查询文件夹下excel的sheet名代码实例
Apr 02 Python
在Python函数中输入任意数量参数的实例
Jul 16 Python
python求质数列表的例子
Nov 24 Python
jupyter notebook参数化运行python方式
Apr 10 Python
解决python 虚拟环境删除包无法加载的问题
Jul 13 Python
Python通过zookeeper实现分布式服务代码解析
Jul 22 Python
python 实现学生信息管理系统的示例
Nov 28 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
ThinkPHP3.1新特性之字段合法性检测详解
2014/06/19 PHP
Laravel5权限管理方法详解
2016/07/26 PHP
功能强大的php文件上传类
2016/08/29 PHP
PHP 用session与gd库实现简单验证码生成与验证的类方法
2016/11/15 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
详解PHP中的外观模式facade pattern
2018/02/05 PHP
jQuery的运行机制和设计理念分析
2011/04/05 Javascript
Extjs中的GridPanel隐藏列会显示在menuDisabled中解决方法
2013/01/27 Javascript
利用js实现遮罩以及弹出可移动登录窗口
2013/07/08 Javascript
javascript动态向网页中添加表格实现代码
2014/02/19 Javascript
javascript判断chrome浏览器的方法
2014/03/26 Javascript
JS匿名函数实例分析
2016/11/26 Javascript
js实现漫天星星效果
2017/01/19 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
web前端vue实现插值文本和输出原始html
2018/01/19 Javascript
jQuery实现文件编码成base64并通过AJAX上传的方法
2018/04/12 jQuery
React.js组件实现拖拽排序组件功能过程解析
2020/04/27 Javascript
JavaScript大数相加相乘的实现方法实例
2020/10/18 Javascript
PHP 502bad gateway原因及解决方案
2020/11/13 Javascript
Python中的defaultdict模块和namedtuple模块的简单入门指南
2015/04/01 Python
Python多线程编程(一):threading模块综述
2015/04/05 Python
python使用xlrd与xlwt对excel的读写和格式设定
2017/01/21 Python
利用Python找出序列中出现最多的元素示例代码
2017/12/08 Python
python实现简单加密解密机制
2019/03/19 Python
PyQt5 在label显示的图片中绘制矩形的方法
2019/06/17 Python
python虚拟环境完美部署教程
2019/08/06 Python
Python修改列表值问题解决方案
2020/03/06 Python
css3实现可滑动跳转的分页插件示例
2014/05/08 HTML / CSS
马来西亚时装购物网站:ZALORA马来西亚
2017/03/14 全球购物
EMPHASIS艾斐诗官网:周生生旗下原创精品珠宝品牌
2020/12/17 全球购物
优秀员工自荐信范文
2013/10/05 职场文书
售房委托书
2014/08/30 职场文书
中学生国庆节演讲稿2015
2015/07/30 职场文书
六年级作文之自救
2019/12/19 职场文书
iPhone13 Pro外观确定,升级4800万镜头,4月20日发新品
2021/04/15 数码科技