相信很多朋友在编程的时候都会想修改一下已经写好的程序行为代码,而最常见的方式就是通过子类来重写父类的一些不满足需求的方法。比如说下面这个例子。

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         )

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

总结

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