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使用urllib2实现发送带cookie的请求
Apr 28 Python
python-django中的APPEND_SLASH实现方法
Jun 21 Python
python基于FTP实现文件传输相关功能代码实例
Sep 28 Python
使用python代码进行身份证号校验的实现示例
Nov 21 Python
pytorch动态网络以及权重共享实例
Jan 06 Python
Python自动采集微信联系人的实现示例
Feb 28 Python
python中数据库like模糊查询方式
Mar 02 Python
Python 批量读取文件中指定字符的实现
Mar 06 Python
python golang中grpc 使用示例代码详解
Jun 03 Python
Python 如何测试文件是否存在
Jul 31 Python
pytorch fine-tune 预训练的模型操作
Jun 03 Python
如何在python中实现ECDSA你知道吗
Nov 23 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
thinkPHP中验证码的简单使用方法
2015/12/26 PHP
基于PHP实现邮箱验证激活过程详解
2020/10/28 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
[原创]用javascript实现检测指定目录是否存在的方法
2008/01/12 Javascript
简略的前端架构心得&amp;&amp;基于editor为例子的编码小技巧
2010/11/25 Javascript
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
2011/09/22 Javascript
利用jquery包将字符串生成二维码图片
2013/09/12 Javascript
javascript创建createXmlHttpRequest对象示例代码
2014/02/10 Javascript
在JavaScript里防止事件函数高频触发和高频调用的方法
2014/09/06 Javascript
JS不完全国际化&amp;本地化手册 之 理论篇
2016/09/27 Javascript
从零开始学习搭建React脚手架项目
2018/08/23 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
2018/11/07 Javascript
js中addEventListener()与removeEventListener()用法案例分析
2020/03/02 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
Python程序语言快速上手教程
2012/07/18 Python
对python numpy.array插入一行或一列的方法详解
2019/01/29 Python
python 列表中[ ]中冒号‘:’的作用
2019/04/30 Python
python 用所有标点符号分隔句子的示例
2019/07/15 Python
在pytorch中查看可训练参数的例子
2019/08/18 Python
Python Tkinter模块 GUI 可视化实例
2019/11/20 Python
解决Numpy中sum函数求和结果维度的问题
2019/12/06 Python
opencv3/python 鼠标响应操作详解
2019/12/11 Python
python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性
2020/02/25 Python
Python3 io文本及原始流I/O工具用法详解
2020/03/23 Python
pycharm通过anaconda安装pyqt5的教程
2020/03/24 Python
Wiggle中国:英国骑行、跑步、游泳 & 铁三运动装备专卖网店
2016/08/02 全球购物
国际知名设计师时装商店:Coggles
2016/09/05 全球购物
斯洛伐克家具和时尚装饰品购物网站:Butlers.sk
2019/09/08 全球购物
Python文件操作的面试题
2013/06/22 面试题
英语专业学生个人求职信范文
2014/01/06 职场文书
幼儿园六一儿童节主持节目串词
2014/03/21 职场文书
学习保证书范文
2014/04/30 职场文书
党员个人承诺书
2015/04/27 职场文书
vue+springboot实现登录验证码
2021/05/27 Vue.js
教你用Java Swing实现自助取款机系统
2021/06/11 Java/Android
JavaScript事件的委托(代理)的用法示例详解
2022/02/18 Javascript