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 相关文章推荐
自动化Nginx服务器的反向代理的配置方法
Jun 28 Python
快速实现基于Python的微信聊天机器人示例代码
Mar 03 Python
python3 pillow生成简单验证码图片的示例
Sep 19 Python
对Python使用mfcc的两种方式详解
Jan 09 Python
python多任务及返回值的处理方法
Jan 22 Python
python 定时器,实现每天凌晨3点执行的方法
Feb 20 Python
对python中url参数编码与解码的实例详解
Jul 25 Python
python爬虫 线程池创建并获取文件代码实例
Sep 28 Python
Pytorch Tensor 输出为txt和mat格式方式
Jan 03 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
Jun 02 Python
详解Python模块化编程与装饰器
Jan 16 Python
自动在Windows中运行Python脚本并定时触发功能实现
Sep 04 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判断字符以及字符串的包含方法属性
2008/08/30 PHP
PHP7扩展开发教程之Hello World实现方法示例
2017/08/03 PHP
Smarty模板配置实例简析
2019/07/20 PHP
PHP高并发和大流量解决方案整理
2019/12/24 PHP
JavaScript 对象模型 执行模型
2009/12/06 Javascript
IE和firefox浏览器的event事件兼容性汇总
2009/12/06 Javascript
jQuery对象数据缓存Cache原理及jQuery.data方法区别介绍
2013/04/07 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
2015/02/17 Javascript
javascript模拟php函数in_array
2015/04/27 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
2015/11/02 Javascript
逻辑表达式中与或非的用法详解
2016/06/06 Javascript
微信小程序开发的四十个技术窍门总结(推荐)
2017/01/23 Javascript
JS简单实现数组去重的方法示例
2017/03/27 Javascript
JavaScript中的一些隐式转换和总结(推荐)
2017/12/22 Javascript
vue+iview+less 实现换肤功能
2018/08/17 Javascript
Vue从TodoList中学父子组件通信
2019/02/05 Javascript
nuxt配置通过指定IP和端口访问的实现
2020/01/08 Javascript
Taro小程序自定义顶部导航栏功能的实现
2020/12/17 Javascript
微信小程序 接入腾讯地图的两种写法
2021/01/12 Javascript
Python字符串匹配算法KMP实例
2015/07/18 Python
使用python调用zxing库生成二维码图片详解
2017/01/10 Python
解决PyCharm中光标变粗的问题
2017/08/05 Python
python之django母板页面的使用
2018/07/03 Python
详解Python的数据库操作(pymysql)
2019/04/04 Python
50行Python代码获取高考志愿信息的实现方法
2019/07/23 Python
pytorch::Dataloader中的迭代器和生成器应用详解
2020/01/03 Python
IE兼容css3圆角的实现代码
2011/07/21 HTML / CSS
美国在线家装零售商:Build.com
2016/09/02 全球购物
Theo + George官方网站:都柏林时尚品牌
2019/04/08 全球购物
最新远光软件笔试题面试题内容
2013/11/08 面试题
工程部经理岗位职责
2015/02/02 职场文书
酒店财务经理岗位职责
2015/04/08 职场文书
初中班主任培训心得体会
2016/01/07 职场文书
浅析Python实现DFA算法
2021/06/26 Python
Java线程的6种状态与生命周期
2022/05/11 Java/Android
戴尔Win11系统no bootable devices found解决教程
2022/09/23 数码科技