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 相关文章推荐
详解python3实现的web端json通信协议
Dec 29 Python
解决pandas无法在pycharm中使用plot()方法显示图像的问题
May 24 Python
numpy.linspace 生成等差数组的方法
Jul 02 Python
django用户登录和注销的实现方法
Jul 16 Python
opencv python 傅里叶变换的使用
Jul 21 Python
python采集微信公众号文章
Dec 20 Python
Python3.x+pyqtgraph实现数据可视化教程
Mar 14 Python
django实现后台显示媒体文件
Apr 07 Python
Python建造者模式案例运行原理解析
Jun 29 Python
Python 如何实现数据库表结构同步
Sep 29 Python
Django自带用户认证系统使用方法解析
Nov 12 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
Nov 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函数
2006/10/09 PHP
PHP四舍五入、取整、round函数使用示例
2015/02/06 PHP
PHP实现类似题库抽题效果
2018/08/16 PHP
PHP中的异常处理机制深入讲解
2020/11/10 PHP
第一个JavaScript入门基础 document.write输出
2010/02/22 Javascript
JS重要知识点小结
2011/11/06 Javascript
刷新页面的几种方法小结(JS,ASP.NET)
2014/01/07 Javascript
Jquery动态替换div内容及动态展示的方法
2015/01/23 Javascript
原生JavaScript编写canvas版的连连看游戏
2016/05/29 Javascript
jQuery实用密码强度检测
2017/03/02 Javascript
看看“疫苗查询”小程序有温度的代码
2018/07/31 Javascript
Vue核心概念Getter的使用方法
2019/01/18 Javascript
详解微信小程序文件下载--视频和图片
2019/04/24 Javascript
Vue CLI3中使用compass normalize的方法
2019/05/30 Javascript
vue动态路由:路由参数改变,视图不更新问题的解决
2019/11/05 Javascript
javascript实现视频弹幕效果(两个版本)
2019/11/28 Javascript
JS实现盒子拖拽效果
2020/02/06 Javascript
[51:30]OG vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.26
2018/08/30 DOTA
pandas apply 函数 实现多进程的示例讲解
2018/04/20 Python
Django开发中的日志输出的方法
2018/07/02 Python
Python迭代器与生成器用法实例分析
2018/07/09 Python
python中map的基本用法示例
2018/09/10 Python
python BlockingScheduler定时任务及其他方式的实现
2019/09/19 Python
Python return语句如何实现结果返回调用
2020/10/15 Python
Django xadmin安装及使用详解
2020/10/26 Python
Pycharm安装python库的方法
2020/11/24 Python
python实现企业微信定时发送文本消息的示例代码
2020/11/24 Python
解决PDF 转图片时丢文字的一种可能方式
2021/03/04 Python
HTML5中使用json对象的实例代码
2018/09/10 HTML / CSS
Marriott中国:万豪国际酒店查询预订
2016/09/02 全球购物
Vita Fede官网:在意大利手工制作,在纽约市设计
2019/10/25 全球购物
北京某科技有限公司C# .net笔试题
2014/09/27 面试题
中考冲刺决心书
2014/03/11 职场文书
年终总结会议主持词
2014/03/17 职场文书
单位证明范文
2015/06/18 职场文书
2016暑期社会实践新闻稿
2015/11/25 职场文书