简单上手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实现web方式logview的方法
Aug 10 Python
Python中使用bidict模块双向字典结构的奇技淫巧
Jul 12 Python
python检查URL是否正常访问的小技巧
Feb 25 Python
python编程实现随机生成多个椭圆实例代码
Jan 03 Python
使用python判断你是青少年还是老年人
Nov 29 Python
基于Python打造账号共享浏览器功能
May 30 Python
python实现修改固定模式的字符串内容操作示例
Dec 30 Python
Tensorflow Summary用法学习笔记
Jan 10 Python
Python原始套接字编程实例解析
Jan 29 Python
Python建造者模式案例运行原理解析
Jun 29 Python
python之随机数函数的实现示例
Dec 30 Python
python利用xpath爬取网上数据并存储到django模型中
Feb 26 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的历史和优缺点
2006/10/09 PHP
PHP也可以?成Shell Script
2006/10/09 PHP
一个odbc连mssql分页的类
2006/10/09 PHP
php页面函数设置超时限制的方法
2014/12/01 PHP
php+ajax简单实现全选删除的方法
2016/12/06 PHP
php实现获取农历(阴历)、节日、节气的类与用法示例
2017/11/20 PHP
PHP+MySQL实现在线测试答题实例
2020/01/02 PHP
PHP数组Key强制类型转换实现原理解析
2020/09/01 PHP
利用javascript查看html源文件
2006/11/08 Javascript
脚本吧 - 幻宇工作室用到js,超强推荐expand.js
2006/12/23 Javascript
jQuery 1.4 15个你应该知道的新特性(译)
2010/01/24 Javascript
JavaScript操作XML实例代码(获取新闻标题并分页,并分页)
2010/05/25 Javascript
jquery动画2.元素坐标动画效果(创建一个图片走廊)
2012/08/24 Javascript
JavaScript var声明变量背后的原理示例解析
2013/10/12 Javascript
jQuery中的val()示例应用
2014/02/26 Javascript
JavaScript中的Math 使用介绍
2014/04/21 Javascript
jQuery及JS实现循环中暂停的方法
2015/02/02 Javascript
javascript中for/in循环及使用技巧
2015/09/01 Javascript
使用微信内置浏览器点击下拉框出现页面乱跳转现象(iphone),该怎么办
2016/01/04 Javascript
vue的props实现子组件随父组件一起变化
2016/10/27 Javascript
对比分析Django的Q查询及AngularJS的Datatables分页插件
2017/02/07 Javascript
详解.vue文件中style标签的几个标识符
2018/07/17 Javascript
JavaScript中七种流行的开源机器学习框架
2018/10/11 Javascript
微信小程序实现点击导航标签滚动定位到对应位置
2020/11/19 Javascript
Windows下安装python2和python3多版本教程
2017/03/30 Python
Python3实现将本地JSON大数据文件写入MySQL数据库的方法
2018/06/13 Python
Win10里python3创建虚拟环境的步骤
2020/01/31 Python
Python使用os.listdir和os.walk获取文件路径
2020/05/21 Python
将keras的h5模型转换为tensorflow的pb模型操作
2020/05/25 Python
pandas实现导出数据的四种方式
2020/12/13 Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
2021/02/25 Python
中国排名第一的外贸销售网站:LightInTheBox.com(兰亭集势)
2016/10/28 全球购物
关于安全的演讲稿
2014/05/09 职场文书
居委会四风问题个人对照检查材料
2014/09/25 职场文书
思品教学工作总结
2015/08/10 职场文书
python使用pygame创建精灵Sprite
2021/04/06 Python