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 相关文章推荐
Windows下安装python2.7及科学计算套装
Mar 05 Python
简单介绍Python中的JSON模块
Apr 08 Python
在Python中使用SimpleParse模块进行解析的教程
Apr 11 Python
在Python中操作文件之seek()方法的使用教程
May 24 Python
Python Pywavelet 小波阈值实例
Jan 09 Python
PyQt5实现简单数据标注工具
Mar 18 Python
python日期相关操作实例小结
Jun 24 Python
Django中的用户身份验证示例详解
Aug 07 Python
pytorch程序异常后删除占用的显存操作
Jan 13 Python
Python开发之pip安装及使用方法详解
Feb 21 Python
详解Python高阶函数
Aug 15 Python
python实现图片批量压缩
Apr 24 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
php中实现精确设置session过期时间的方法
2014/07/17 PHP
Yii编程开发常见调用技巧集锦
2016/07/15 PHP
php车辆违章查询数据示例
2016/10/14 PHP
php实现的mysqldb读写分离操作类示例
2017/02/07 PHP
PHP中ajax无刷新上传图片与图片下载功能
2017/02/21 PHP
超级兔子让浮动层消失的前因后果
2007/03/09 Javascript
CSS和Javascript简单复习资料
2010/06/29 Javascript
25个优雅的jQuery Tooltip插件推荐
2011/05/25 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
node.js中的fs.futimes方法使用说明
2014/12/17 Javascript
jQuery实现自定义checkbox和radio样式
2015/07/13 Javascript
简单易懂的天气插件(代码分享)
2017/02/04 Javascript
vue-cli webpack 开发环境跨域详解
2017/05/18 Javascript
JS仿淘宝搜索框用户输入事件的实现
2017/06/19 Javascript
微信小程序实现多宫格抽奖活动
2020/04/15 Javascript
Vue跨域请求问题解决方案过程解析
2020/08/07 Javascript
js动态添加带圆圈序号列表的实例代码
2021/02/18 Javascript
[47:08]OG vs INfamous 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python中is与双等于号“==”的区别示例详解
2017/11/21 Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
2018/09/04 Python
VScode连接远程服务器上的jupyter notebook的实现
2020/04/23 Python
htnl5利用svg页面高斯模糊的方法
2018/07/20 HTML / CSS
美国最受欢迎的度假租赁网站:VRBO
2016/08/02 全球购物
JD Sports西班牙:英国领先的运动服装公司
2020/01/06 全球购物
C# Debug和Testing相关面试题
2015/10/25 面试题
介绍一下JMS编程步骤
2015/09/22 面试题
生产部经理岗位职责
2013/12/16 职场文书
通信生自我鉴定
2014/01/18 职场文书
最新会计专业求职信范文
2014/01/28 职场文书
班级光棍节联谊会策划书
2014/10/10 职场文书
勤俭节约倡议书范文
2015/04/29 职场文书
团队执行力培训心得体会
2015/08/15 职场文书
Html5新增了哪些功能
2021/04/16 HTML / CSS
Go 实现英尺和米的简单单位换算方式
2021/04/29 Golang
nginx作grpc的反向代理踩坑总结
2021/07/07 Servers
MySQL数据库完全卸载的方法
2022/03/03 MySQL