简单理解Python中的装饰器


Posted in Python onJuly 31, 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思想中的装饰器的实现, 其本质也只是使用了闭包的思路, 延迟调用, 并在调用前后增加自己的其他实现内容

Ps: 以上皆为学习笔记, 附带自己的理解, 难免有偏差, 如有发现纰漏, 还望指正

Python 相关文章推荐
python爬虫入门教程之点点美女图片爬虫代码分享
Sep 02 Python
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
Feb 04 Python
Python最基本的数据类型以及对元组的介绍
Apr 14 Python
Numpy中矩阵matrix读取一列的方法及数组和矩阵的相互转换实例
Jul 02 Python
python实现键盘控制鼠标移动
Nov 27 Python
Python实现求两个数组交集的方法示例
Feb 23 Python
opencv导入头文件时报错#include的解决方法
Jul 31 Python
tensorflow 模型权重导出实例
Jan 24 Python
pandas DataFrame运算的实现
Jun 14 Python
python字典key不能是可以是啥类型
Aug 04 Python
python MD5加密的示例
Oct 19 Python
python 爬虫如何实现百度翻译
Nov 16 Python
python简单分割文件的方法
Jul 30 #Python
Python读取网页内容的方法
Jul 30 #Python
python查看FTP是否能连接成功的方法
Jul 30 #Python
python如何实现excel数据添加到mongodb
Jul 30 #Python
python学习之第三方包安装方法(两种方法)
Jul 30 #Python
Python实现的Excel文件读写类
Jul 30 #Python
Djang中静态文件配置方法
Jul 30 #Python
You might like
确保Laravel网站不会被嵌入到其他站点中的方法
2019/10/18 PHP
js操作输入框提示信息且响应鼠标事件
2014/03/25 Javascript
javascript模拟实现ajax加载框实例
2014/10/15 Javascript
JS通过ajax动态读取xml文件内容的方法
2015/03/24 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
2015/12/04 Javascript
Bootstrap每天必学之按钮(Button)插件
2016/04/25 Javascript
移动端H5开发 Turn.js实现很棒的翻书效果
2016/06/20 Javascript
jQuery的Cookie封装,与PHP交互的简单实现
2016/10/05 Javascript
Javascript使用function创建类的两种方法(推荐)
2016/11/19 Javascript
一篇文章让你彻底弄懂JS的事件冒泡和事件捕获
2017/08/14 Javascript
Vue.js中的computed工作原理
2018/03/22 Javascript
vue+element模态框中新增模态框和删除功能
2019/06/11 Javascript
javascript使用substring实现的展开与收缩文字功能示例
2019/06/17 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
Python下的twisted框架入门指引
2015/04/15 Python
python编程通过蒙特卡洛法计算定积分详解
2017/12/13 Python
教你用Python创建微信聊天机器人
2020/03/31 Python
Django基于ORM操作数据库的方法详解
2018/03/27 Python
Python 堆叠柱状图绘制方法
2019/07/29 Python
docker-py 用Python调用Docker接口的方法
2019/08/30 Python
Django URL参数Template反向解析
2020/11/24 Python
如何提高SQL Server的安全性
2016/07/25 面试题
数据库方面面试题
2012/04/22 面试题
简述安装Slackware Linux系统的过程
2012/01/12 面试题
介绍一下gcc特性
2012/01/20 面试题
linux面试题参考答案(8)
2015/08/11 面试题
有abstract方法的类一定要用abstract修饰吗
2016/03/14 面试题
vue路由实现登录拦截
2021/03/24 Vue.js
英文版区域经理求职信
2013/10/23 职场文书
工业设计专业个人求职信范文
2013/12/28 职场文书
大学生水果店创业计划书
2014/01/28 职场文书
2016国庆节活动宣传语
2015/11/25 职场文书
MySQL里面的子查询的基本使用
2021/08/02 MySQL
为什么RedisCluster设计成16384个槽
2021/09/25 Redis