Python类的动态修改的实例方法


Posted in Python onMarch 24, 2017

Python类的动态修改的实例方法

相信很多朋友在编程的时候都会想修改一下已经写好的程序行为代码,而最常见的方式就是通过子类来重写父类的一些不满足需求的方法。比如说下面这个例子。

class Dog:
  def bark(self):
    print 'Woof!'
 
class Husky(Dog):
  def bark(self)
    print 'Howl!'

我们可以用上述方式来修改我们自己写的代码,但是我们应该怎么修改第三方代码呢?当然,我们也可以自己编写一个子类,调用子类的实例对象来实现修改,但是这样可能会引入其他一系列问题。所以我们得想个办法用我们自己的方法替换掉原来的对象方法,这就是本文接下来要介绍的“打补丁”的方式。

给类打补丁

如果我们想新增或是修改对象的方法的话,最简单的方式莫过于给类打个补丁了。结合上面的例子,如果我们想给我们自己的 Dog 类写一个新的 howl 方法的话,我们可以定义一个新的 howl 函数,像下面的代码一样把它添加到我们的类中:

def newbark(self):
  print 'Wrooof!'
 
def howl(self):
  print 'Howl!'
 
# Replace an existing method
Dog.bark = newbark
 
# Add a new method
Dog.howl = howl

很简单吧?但是这里有几个问题需要我们注意。首先,被修改的类的所有实例中的方法都会被更新,所以更新后的方法不仅仅存在于新创建的对象中,之前创建的所有对象都会拥有更新之后的方法,除非只是新增而不是覆盖掉原来的方法。第二,你修改或者新增的方法应当是与对象绑定的,所以方法的第一个参数应当是被调用的对象(在这里就是类的实例self)。

给类实例打补丁

单个对象也可以在不影响这个类的其他实例的情况下打补丁。但是还是有点小技巧的哦!先让我们看看下面这个例子。

def herd(self, sheep):
  self.run()
  self.bark()
  self.run()
 
border_collie = Dog()
border_collie.herd = herd

然后我们再试试调用新定义的方法:

border_collie.herd(sheep)
 
TypeError: herd() takes exactly 2 arguments (1 given)
The problem with the previous code is that the herd is not a bound method, just take a look at the following code:
 
print border_collie.herd
 
<function herd at 0xf9c5f0>

出错啦!引发错误的原因就是被调用的对象并没有作为第一个参数传给我们写的函数。当然我们可以自己把参数传进去,但是在这个替换类方法的场景下并不奏效。解决这个问题的正确方案是用 type 这个模块里的 MethodType 函数,我们可以看看下面的示例代码:

import types
 
border_collie = Dog()
border_collie.herd = types.MethodType(herd, border_collie)
 
print border_collie.herd
<bound method ?.herd of <__main__.Dog instance at 0x23c9518>>
 
border_collie.herd(sheep)

现在我们的方法已经和实例绑定了,大功告成!

总结

运行中替换或者添加方法是非常有用的,比如说在单元测试中,有些负责和外界服务通信的函数就需要替换掉,方便测试。这个技巧不仅很常用,而且在你最终决定要修改代码之前还可以保持代码的可维护性,是一个非常重要的技巧。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
python求素数示例分享
Feb 16 Python
Python中的hypot()方法使用简介
May 18 Python
Python面向对象class类属性及子类用法分析
Feb 02 Python
Python统计python文件中代码,注释及空白对应的行数示例【测试可用】
Jul 25 Python
使用python判断jpeg图片的完整性实例
Jun 10 Python
利用python计算时间差(返回天数)
Sep 07 Python
python 实现多线程下载m3u8格式视频并使用fmmpeg合并
Nov 15 Python
Python读取Excel数据并生成图表过程解析
Jun 18 Python
tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this T
Jun 22 Python
python性能测试工具locust的使用
Dec 28 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
Jan 27 Python
解决pytorch下出现multi-target not supported at的一种可能原因
Feb 06 Python
Python操作Excel之xlsx文件
Mar 24 #Python
解决uWSGI的编码问题详解
Mar 24 #Python
Python中动态创建类实例的方法
Mar 24 #Python
python3中set(集合)的语法总结分享
Mar 24 #Python
Python Socket编程详细介绍
Mar 23 #Python
python3中int(整型)的使用教程
Mar 23 #Python
python利用Guetzli批量压缩图片
Mar 23 #Python
You might like
教你如何快捷的使用cmd访问mysql小技巧
2014/05/26 PHP
示例详解Laravel的注册重构
2016/08/14 PHP
Yii2 如何在modules中添加验证码的方法
2017/06/19 PHP
简单JS代码压缩器
2006/10/12 Javascript
javascript实现面向对象类的功能书写技巧
2010/03/07 Javascript
JQuery 文本框回车跳到下一个文本框示例代码
2013/08/30 Javascript
js字符串日期yyyy-MM-dd转化为date示例代码
2014/03/06 Javascript
常用的js验证和数据处理总结
2016/08/02 Javascript
jQuery Ajax使用FormData对象上传文件的方法
2016/09/07 Javascript
JQuery学习总结【一】
2016/12/01 Javascript
JavaScript BASE64算法实现(完美解决中文乱码)
2017/01/10 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
node中的session的具体使用
2018/09/14 Javascript
Nodejs异步流程框架async的方法
2019/06/07 NodeJs
vue实现倒计时获取验证码效果
2020/04/17 Javascript
浅谈vue中组件绑定事件时是否加.native
2019/11/09 Javascript
vue2.0 watch里面的 deep和immediate用法说明
2020/10/30 Javascript
[01:10]DOTA2亚洲邀请赛 征战号角响彻全场
2015/01/06 DOTA
python操作列表的函数使用代码详解
2017/12/28 Python
tensorflow 中对数组元素的操作方法
2018/07/27 Python
python3 pygame实现接小球游戏
2019/05/14 Python
python tqdm实现进度条的示例代码
2020/11/10 Python
python3中数组逆序输出方法
2020/12/01 Python
HTML5 Canvas+JS控制电脑或手机上的摄像头实例
2014/05/03 HTML / CSS
数据库连接池的工作原理
2012/09/26 面试题
Java TransactionAPI (JTA) 主要包含几部分
2012/12/07 面试题
幼儿园毕业教师感言
2014/02/21 职场文书
销售行政专员岗位职责
2014/06/10 职场文书
离婚财产处理协议书
2014/09/30 职场文书
数学考试作弊检讨书300字
2015/02/16 职场文书
工作失职检讨书范文
2015/05/05 职场文书
2015年党建工作汇报材料
2015/06/25 职场文书
初中班主任培训心得体会
2016/01/07 职场文书
诚信高考倡议书
2019/06/24 职场文书
Mysql数据库按时间点恢复实战记录
2021/06/30 MySQL
pt-archiver 主键自增
2022/04/26 MySQL