Python类的动态修改的实例方法

作者:平和的心 时间:2021-07-03 12:16:15 

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)

现在我们的方法已经和实例绑定了,大功告成!

总结

运行中替换或者添加方法是非常有用的,比如说在单元测试中,有些负责和外界服务通信的函数就需要替换掉,方便测试。这个技巧不仅很常用,而且在你最终决定要修改代码之前还可以保持代码的可维护性,是一个非常重要的技巧。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

来源:http://www.cnblogs.com/ajianbeyourself/p/4916254.html

标签:动态修改,Python类
0
投稿

猜你喜欢

  • Python图像处理库PIL的ImageFont模块使用介绍

    2023-12-20 10:30:42
  • Python基本数据类型之字符串str

    2021-06-03 22:47:31
  • JavaScript观察者模式(publish/subscribe)原理与实现方法

    2024-04-10 10:44:15
  • 如何通过阿里云实现动态域名解析DDNS的方法

    2022-05-30 23:04:50
  • 4个场景教会你Go中Goroutine和通道是怎么用的

    2024-04-23 09:45:05
  • 基于tensorflow for循环 while循环案例

    2022-01-26 14:40:34
  • 详解如何运行vue项目

    2024-05-13 09:09:47
  • Python采集王者最低战力信息实战示例

    2021-09-29 17:54:13
  • SQL server 2016 安装步骤图文教程

    2024-01-26 07:55:59
  • python使用 cx_Oracle 模块进行查询操作示例

    2022-06-17 05:55:24
  • asp.net mvc4 mysql制作简单分页组件(部分视图)

    2024-01-27 17:56:36
  • Flask  request 对象介绍

    2022-11-01 23:45:35
  • selenium+opencv实现滑块验证码的登陆

    2022-03-28 06:49:04
  • Dreamweaver处理word文档有妙招

    2008-05-23 13:00:00
  • Python文本处理简单易懂方法解析

    2021-08-09 02:45:16
  • 整理关于Bootstrap表单的慕课笔记

    2024-04-16 10:27:19
  • sogou地图API用法实例教程

    2024-04-16 10:30:08
  • php实现汉字验证码和算式验证码的方法

    2024-06-07 15:50:15
  • 解决pip install xxx报错SyntaxError: invalid syntax的问题

    2023-02-13 23:53:07
  • MySQL数据库的23个特别注意事项

    2010-08-08 14:43:00
  • asp之家 网络编程 m.aspxhome.com