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 相关文章推荐
MySQLdb ImportError: libmysqlclient.so.18解决方法
Aug 21 Python
python使用Tkinter显示网络图片的方法
Apr 24 Python
Python中的map()函数和reduce()函数的用法
Apr 27 Python
Python读写文件方法总结
Jun 09 Python
Python文件打开方式实例详解【a、a+、r+、w+区别】
Mar 30 Python
Kears+Opencv实现简单人脸识别
Aug 28 Python
python 五子棋如何获得鼠标点击坐标
Nov 04 Python
TensorFlow获取加载模型中的全部张量名称代码
Feb 11 Python
django 扩展user用户字段inlines方式
Mar 30 Python
Python函数参数定义及传递方式解析
Jun 10 Python
详解python3 GUI刷屏器(附源码)
Feb 18 Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
Mar 02 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
解析在zend Farmework下如何创立一个FORM表单
2013/06/28 PHP
简介PHP的Yii框架中缓存的一些高级用法
2016/03/29 PHP
利用php生成验证码
2017/02/23 PHP
php模式设计之观察者模式应用实例分析
2019/09/25 PHP
javascript HTMLEncode HTMLDecode的完整实例(兼容ie和火狐)
2009/06/02 Javascript
jQueryPad 实用的jQuery测试工具(支持IE,chrome,FF)
2010/05/22 Javascript
jquery 操作DOM的基本用法分享
2012/04/05 Javascript
js判断样式className同时增加class或删除class
2013/01/30 Javascript
jquery使用淘宝接口跨域查询手机号码归属地实例
2013/11/28 Javascript
jQuery中focus事件用法实例
2014/12/26 Javascript
Angular 路由route实例代码
2016/07/12 Javascript
js学习笔记之事件处理模型
2016/10/31 Javascript
bootstrap输入框组使用方法
2017/02/07 Javascript
使用jQuery.Pin垂直滚动时固定导航
2017/05/24 jQuery
JS严格模式知识点总结
2018/02/27 Javascript
微信小程序开发之自定义tabBar的实现
2018/09/06 Javascript
vue.js中proxyTable 转发请求的实现方法
2018/09/20 Javascript
WebGL three.js学习笔记之阴影与实现物体的动画效果
2019/04/25 Javascript
微信小程序如何使用云开发
2019/05/17 Javascript
python:print格式化输出到文件的实例
2018/05/14 Python
Python读取数据集并消除数据中的空行方法
2018/07/12 Python
python 删除字符串中连续多个空格并保留一个的方法
2018/12/22 Python
详解Python打包分发工具setuptools
2019/08/05 Python
python实现智能语音天气预报
2019/12/02 Python
Python tkinter实现图片标注功能(完整代码)
2019/12/08 Python
Python 实现将数组/矩阵转换成Image类
2020/01/09 Python
python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案
2020/08/11 Python
关于iframe跨域使用postMessage的实现
2019/10/29 HTML / CSS
荷兰多品牌网上鞋店:Stoute Schoenen
2017/08/24 全球购物
Maison Lab荷兰:名牌Outlet购物
2018/08/10 全球购物
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
师范应届毕业生自荐信
2013/11/18 职场文书
面试自我评价范文
2014/09/17 职场文书
酒店辞职书范文
2015/02/26 职场文书
2019年让高校“心动”的自荐信
2019/03/25 职场文书
Mysql基础知识点汇总
2021/05/26 MySQL