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之重回函数
Oct 10 Python
python中requests小技巧
May 10 Python
windows下安装Python的XlsxWriter模块方法
May 03 Python
python实现名片管理系统
Nov 29 Python
Python实现微信中找回好友、群聊用户撤回的消息功能示例
Aug 23 Python
python中调试或排错的五种方法示例
Sep 12 Python
对tensorflow中cifar-10文档的Read操作详解
Feb 10 Python
Python numpy多维数组实现原理详解
Mar 10 Python
基于nexus3配置Python仓库过程详解
Jun 15 Python
matplotlib基础绘图命令之imshow的使用
Aug 13 Python
python中print格式化输出的问题
Apr 16 Python
OpenCV-Python实现人脸磨皮算法
Jun 07 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编程效率 引入缓存机制提升性能
2010/02/15 PHP
php缓冲输出实例分析
2015/01/05 PHP
PHP使用正则表达式获取微博中的话题和对象名
2015/07/18 PHP
一个收集图片的bookmarlet(js 刷新页面中的图片)
2010/05/27 Javascript
利用jQuery操作对象数组的实现代码
2011/04/27 Javascript
javascript 正则表达式相关应介绍
2012/11/27 Javascript
如何用js控制frame的隐藏或显示的解决办法
2013/03/20 Javascript
javascript中键盘事件用法实例分析
2015/01/30 Javascript
使用jQuery制作基础的Web图片轮播效果
2016/04/22 Javascript
微信小程序 实战实例开发流程详细介绍
2017/01/05 Javascript
微信小程序 封装http请求实例详解
2017/01/16 Javascript
loading动画特效小结
2017/01/22 Javascript
webpack vue 项目打包生成的文件,资源文件报404问题的修复方法(总结篇)
2018/01/09 Javascript
详解使用VUE搭建后台管理系统(vue-cli更新至3.0)
2018/08/22 Javascript
微信小程序复选框实现多选一功能过程解析
2020/02/14 Javascript
js实现经典贪吃蛇小游戏
2020/03/19 Javascript
OpenLayers加载缩放控件使用方法详解
2020/09/25 Javascript
python UNIX_TIMESTAMP时间处理方法分析
2016/04/18 Python
Python数据结构与算法之完全树与最小堆实例
2017/12/13 Python
pycharm中显示CSS提示的知识点总结
2019/07/29 Python
Django 大文件下载实现过程解析
2019/08/01 Python
python3 pillow模块实现简单验证码
2019/10/31 Python
如何基于python生成list的所有的子集
2019/11/11 Python
Python sorted对list和dict排序
2020/06/09 Python
django序列化时使用外键的真实值操作
2020/07/15 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
10个顶级Python实用库推荐
2021/03/04 Python
阿迪达斯墨西哥官方网站:adidas墨西哥
2017/11/03 全球购物
斯德哥尔摩通票:Stockholm Pass
2018/01/09 全球购物
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
多媒体编辑专业毕业生推荐信
2013/11/05 职场文书
班队活动设计方案
2014/01/30 职场文书
圣诞节红领巾广播稿
2014/02/03 职场文书
双拥工作宣传标语
2014/06/26 职场文书
致三级跳运动员加油稿
2015/07/21 职场文书
MySQL 数据库 增删查改、克隆、外键 等操作
2022/05/11 MySQL