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生成指定尺寸缩略图的示例
May 07 Python
在Python的Django框架中simple-todo工具的简单使用
May 30 Python
Python中防止sql注入的方法详解
Feb 25 Python
Python django使用多进程连接mysql错误的解决方法
Oct 08 Python
django框架使用orm实现批量更新数据的方法
Jun 21 Python
python3实现mysql导出excel的方法
Jul 31 Python
python numpy数组中的复制知识解析
Feb 03 Python
Python类中self参数用法详解
Feb 13 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
Jun 23 Python
Python如何给函数库增加日志功能
Aug 04 Python
python 实现压缩和解压缩的示例
Sep 22 Python
python脚本框架webpy模板赋值实现
Nov 20 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 获取SWF动画截图示例代码
2014/02/10 PHP
PHP循环结构实例讲解
2014/02/10 PHP
在 IE 中调用 javascript 打开 Excel 表
2006/12/21 Javascript
Javascript图像处理—平滑处理实现原理
2012/12/28 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(二)人物行走的实现
2013/01/23 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
document.documentElement的一些使用技巧
2013/04/18 Javascript
JSCode all of Brower 全局屏蔽网页右键功能 具体实现
2013/06/05 Javascript
js控制表单奇偶行样式的简单方法
2013/07/31 Javascript
JavaScript中诡异的delete操作符
2015/03/12 Javascript
基于JS实现PHP的sprintf函数实例
2015/11/14 Javascript
用JS生成UUID的方法实例
2016/03/30 Javascript
node.js中express-session配置项详解
2017/05/31 Javascript
vue实现手机号码抽奖上下滚动动画示例
2017/10/18 Javascript
javaScript实现鼠标在文字上悬浮时弹出悬浮层效果
2020/04/12 Javascript
[55:25]VGJ.T vs Optic Supermajor小组赛D组 BO3 第三场 6.3
2018/06/04 DOTA
Python内置的字符串处理函数详细整理(覆盖日常所用)
2014/08/19 Python
详解Python编程中包的概念与管理
2015/10/16 Python
Python实现注册登录系统
2017/08/08 Python
Python即时网络爬虫项目启动说明详解
2018/02/23 Python
python获取指定字符串中重复模式最高的字符串方法
2018/06/29 Python
详解小白之KMP算法及python实现
2019/04/04 Python
Python使用Pandas对csv文件进行数据处理的方法
2019/08/01 Python
详解Django CAS 解决方案
2019/10/30 Python
Python ATM功能实现代码实例
2020/03/19 Python
PyCharm Ctrl+Shift+F 失灵的简单有效解决操作
2021/01/15 Python
KELLER SPORTS荷兰:在线订购最好的运动产品
2020/10/13 全球购物
校长先进事迹材料
2014/02/01 职场文书
经贸日语专业自荐信
2014/09/02 职场文书
研讨会通知
2015/04/27 职场文书
因个人原因离职的辞职信范文
2015/05/12 职场文书
结婚司仪主持词
2015/06/29 职场文书
导游词之安徽巢湖
2019/12/26 职场文书
go mod 安装依赖 unkown revision问题的解决方案
2021/05/06 Golang
mysql数据库实现设置字段长度
2022/06/10 MySQL
Debian11 Xfce终端光标的颜色怎么设置?
2022/08/14 数码科技