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中实现两个字典(dict)合并的方法
Sep 23 Python
python对url格式解析的方法
May 13 Python
python基于xmlrpc实现二进制文件传输的方法
Jun 02 Python
Python 模块EasyGui详细介绍
Feb 19 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
Dec 03 Python
python MySQLdb使用教程详解
Mar 20 Python
使用python编写udp协议的ping程序方法
Apr 22 Python
用Django写天气预报查询网站
Oct 21 Python
python中hasattr()、getattr()、setattr()函数的使用
Aug 16 Python
python实现爱奇艺登陆密码RSA加密的方法示例详解
May 27 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
Oct 10 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
Nov 05 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/12/05 PHP
php流量统计功能的实现代码
2012/09/29 PHP
PHP中func_get_args(),func_get_arg(),func_num_args()的区别
2013/09/30 PHP
js实现点小图看大图效果的思路及示例代码
2013/10/28 Javascript
关于img的href和src取变量及赋值的方法
2014/04/28 Javascript
js简单设置与使用cookie的方法
2016/01/22 Javascript
javascript的几种继承方法介绍
2016/03/22 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
详解angular2实现ng2-router 路由和嵌套路由
2017/03/24 Javascript
Vue from-validate 表单验证的示例代码
2017/09/26 Javascript
vue中使用sessionStorage记住密码功能
2018/07/24 Javascript
vue-cli 脚手架基于Nightwatch的端到端测试环境的过程
2018/09/30 Javascript
vue项目首屏打开速度慢的解决方法
2019/03/31 Javascript
[05:48]DOTA2英雄梦之声vol21 屠夫
2014/06/20 DOTA
Python中执行存储过程及获取存储过程返回值的方法
2017/10/07 Python
python+selenium实现京东自动登录及秒杀功能
2017/11/18 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
Pycharm无法使用已经安装Selenium的解决方法
2018/10/13 Python
python 实现保存最新的三份文件,其余的都删掉
2019/12/22 Python
pyqt5数据库使用详细教程(打包解决方案)
2020/03/25 Python
win10下python3.8的PIL库安装过程
2020/06/08 Python
使用HTML5 IndexDB存储图像和文件的示例
2018/11/05 HTML / CSS
Carrs Silver官网:英国著名的银器品牌
2020/08/29 全球购物
学生党员一帮一活动总结
2014/07/08 职场文书
英文演讲稿开场白
2014/08/25 职场文书
迎国庆演讲稿
2014/09/05 职场文书
自我查摆剖析材料
2014/10/11 职场文书
毕业实习计划书
2015/01/16 职场文书
财务负责人岗位职责
2015/02/03 职场文书
个人求职信格式范文
2015/03/20 职场文书
员工年度工作总结2015
2015/05/18 职场文书
2015年度合同管理工作总结
2015/05/22 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
pyqt5蒙版遮罩mask,setmask的使用
2021/06/11 Python
Python语言内置数据类型
2022/02/24 Python
MySQL控制流函数(-if ,elseif,else,case...when)
2022/07/07 MySQL