简单上手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简单判断序列是否为空的方法
Jun 30 Python
Python并发编程协程(Coroutine)之Gevent详解
Dec 27 Python
Python cookbook(数据结构与算法)将名称映射到序列元素中的方法
Mar 22 Python
Python3中exp()函数用法分析
Feb 19 Python
Python基本数据结构之字典类型dict用法分析
Jun 08 Python
python调用动态链接库的基本过程详解
Jun 19 Python
命令行运行Python脚本时传入参数的三种方式详解
Oct 11 Python
Python 模拟动态产生字母验证码图片功能
Dec 24 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
python的Jenkins接口调用方式
May 12 Python
Python并发请求下限制QPS(每秒查询率)的实现代码
Jun 05 Python
python ssh 执行shell命令的示例
Sep 29 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
第八节 访问方式 [8]
2006/10/09 PHP
WHOOPS PHP调试库的使用
2017/09/29 PHP
基于javascript 闭包基础分享
2013/07/10 Javascript
jquery1.9 下检测浏览器类型和版本的方法
2013/12/26 Javascript
jQuery的DOM操作之删除节点示例
2014/01/03 Javascript
JS逆序遍历实现代码
2014/12/02 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
实例讲解JavaScript中的this指向错误解决方法
2016/06/13 Javascript
JavaScript数组去重的几种方法效率测试
2016/10/23 Javascript
JavaScript日期选择功能示例
2017/01/16 Javascript
详解webpack+angular2开发环境搭建
2017/06/28 Javascript
webpack 1.x升级过程中的踩坑总结大全
2017/08/09 Javascript
3种vue组件的书写形式
2017/11/29 Javascript
微信小程序使用audio组件播放音乐功能示例【附源码下载】
2017/12/08 Javascript
jQuery插件实现弹性运动完整示例
2018/07/07 jQuery
JavaScript设计模式之单例模式原理与用法实例分析
2018/07/26 Javascript
详解使用VueJS开发项目中的兼容问题
2018/08/02 Javascript
vue动态循环出的多个select出现过的变为disabled(实例代码)
2019/11/10 Javascript
vue任意关系组件通信与跨组件监听状态vue-communication
2020/10/18 Javascript
[01:08]DOTA2次级职业联赛 - Shield战队宣传片
2014/12/01 DOTA
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
2016/11/02 Python
Python中的Numpy矩阵操作
2018/08/12 Python
python实现的MySQL增删改查操作实例小结
2018/12/19 Python
python读取图片的方式,以及将图片以三维数组的形式输出方法
2019/07/03 Python
tensorflow 利用expand_dims和squeeze扩展和压缩tensor维度方式
2020/02/07 Python
python网络编程之五子棋游戏
2020/05/14 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
HTML5 解析规则分析
2009/08/14 HTML / CSS
后勤部长岗位职责
2013/12/14 职场文书
校园创业策划书
2014/01/14 职场文书
《红军不怕远征难》教学反思
2014/04/14 职场文书
化工专业求职信
2014/07/01 职场文书
班级元旦晚会开幕词
2015/01/29 职场文书
六一儿童节开幕词
2015/01/29 职场文书
Elasticsearch 批量操作
2022/04/19 Python
MySQL 自动填充 create_time 和 update_time
2022/05/20 MySQL