简单上手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关键字and和or用法实例
May 28 Python
python检测是文件还是目录的方法
Jul 03 Python
python re模块findall()函数实例解析
Jan 19 Python
解决python中os.listdir()函数读取文件夹下文件的乱序和排序问题
Oct 17 Python
对Python3 解析html的几种操作方式小结
Feb 16 Python
python爬虫 urllib模块发起post请求过程解析
Aug 20 Python
Python aiohttp百万并发极限测试实例分析
Oct 26 Python
Django框架中间件定义与使用方法案例分析
Nov 28 Python
python实现俄罗斯方块小游戏
Apr 24 Python
python的launcher用法知识点总结
Aug 07 Python
golang/python实现归并排序实例代码
Aug 30 Python
怎么解决pycharm license Acti的方法
Oct 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
《魔兽世界》惊魂幻象将获得调整
2020/03/08 其他游戏
BBS(php & mysql)完整版(七)
2006/10/09 PHP
php 数组使用详解 推荐
2011/06/02 PHP
PHP中文竖排转换实现方法
2015/10/23 PHP
PHP基于mcript扩展实现对称加密功能示例
2019/02/21 PHP
利用JQuery+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
2009/10/24 Javascript
解析Node.js基于模块和包的代码部署方式
2016/02/16 Javascript
微信小程序 出现错误:{"baseresponse":{"errcode":-80002,"errmsg":""}}解决办法
2017/02/23 Javascript
微信小程序 开发之全局配置
2017/05/05 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
2017/09/26 Javascript
vue项目中公用footer组件底部位置的适配问题
2018/05/10 Javascript
Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)
2018/05/16 Javascript
security.js实现的RSA加密功能示例
2018/06/06 Javascript
微信小程序如何调用新闻接口实现列表循环
2019/07/02 Javascript
微信小程序实现弹框效果
2020/05/26 Javascript
Element PageHeader页头的使用方法
2020/07/26 Javascript
[49:29]LGD vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
python调用java的Webservice示例
2014/03/10 Python
python中的变量如何开辟内存
2018/06/26 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
Python使用post及get方式提交数据的实例
2019/01/24 Python
python代理工具mitmproxy使用指南
2019/07/04 Python
mac系统下Redis安装和使用步骤详解
2019/07/09 Python
Python+OpenCV实现实时眼动追踪的示例代码
2019/11/11 Python
python dataframe NaN处理方式
2019/12/26 Python
python def 定义函数,调用函数方式
2020/06/02 Python
CSS3 3D制作实战案例分析
2016/09/18 HTML / CSS
浅谈关于html5中图片抛物线运动的一些心得
2018/01/09 HTML / CSS
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
理肤泉美国官网:La Roche-Posay
2018/01/17 全球购物
回馈慈善的设计师太阳镜:DIFF eyewear
2019/10/17 全球购物
介绍一下sql server的安全性
2014/08/10 面试题
超市开学活动方案
2014/03/01 职场文书
毕业生捐书活动倡议书
2015/04/27 职场文书
《观察物体》教学反思
2016/02/17 职场文书
Java8中Stream的一些神操作
2021/11/02 Java/Android