相信很多朋友在编程的时候都会想修改一下已经写好的程序行为代码,而最常见的方式就是通过子类来重写父类的一些不满足需求的方法。比如说下面这个例子。
Python
class Dog :
def bark ( self ) :
print 'Woof!'
class Husky ( Dog ) :
def bark ( self )
print 'Howl!'
我们可以用上述方式来修改我们自己写的代码,但是我们应该怎么修改第三方代码呢?当然,我们也可以自己编写一个子类,调用子类的实例对象来实现修改,但是这样可能会引入其他一系列问题。所以我们得想个办法用我们自己的方法替换掉原来的对象方法,这就是本文接下来要介绍的“打补丁”的方式。
如果我们想新增或是修改对象的方法的话,最简单的方式莫过于给类打个补丁了。结合上面的例子,如果我们想给我们自己的 Dog 类写一个新的 howl 方法的话,我们可以定义一个新的 howl
Python
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)。
单个对象也可以在不影响这个类的其他实例的情况下打补丁。但是还是有点小技巧的哦!先让我们看看下面这个例子。
Python
1 2 3 4 5 6 7 | def herd ( self , sheep ) : self . run ( ) self . bark ( ) self . run ( )
border_collie = Dog ( ) border_collie . herd = herd |
然后我们再试试调用新定义的方法:
Python
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
Python
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 )
现在我们的方法已经和实例绑定了,大功告成!
运行中替换或者添加方法是非常有用的,比如说在单元测试中,有些负责和外界服务通信的函数就需要替换掉,方便测试。这个技巧不仅很常用,而且在你最终决定要修改代码之前还可以保持代码的可维护性,是一个非常重要的技巧。