page contents

浅谈猴子补丁

属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。 为什么叫猴子补丁 属性的运行时替换和猴子也没什么关系,关于猴子补丁的由来网上查到两种说法: 1.这个词原来为Guerrilla Patch,...
属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。

为什么叫猴子补丁
属性的运行时替换和猴子也没什么关系,关于猴子补丁的由来网上查到两种说法:
1.这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。
2.还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。
猴子补丁的叫法有些莫名其妙,只要和“模块运行时替换的功能”对应就行了。

猴子补丁的用法

1、运行时动态替换模块的方法
stackoverflow上有两个比较热的例子,

  1. consider a class that has a method get_data. This method does an
  2. external lookup (on a database or web API, for example), and various
  3. other methods in the class call it. However, in a unit test, you don't
  4. want to depend on the external data source - so you dynamically
  5. replace the get_data method with a stub that returns some fixed data.

假设一个类有一个方法get_data。这个方法做一些外部查询(如查询数据库或者Web API等),类里面的很多其他方法都调用了它。然而,在一个单元测试中,你不想依赖外部数据源。所以你用哑方法态替换了这个get_data方法,哑方法只返回一些测试数据。
另一个例子引用了,Zope wiki上对Monkey Patch解释:

  1. from SomeOtherProduct.SomeModule import SomeClass
  2. def speak(self):
  3. return "ook ook eee eee eee!"
  4. SomeClass.speak = speak

还有一个比较实用的例子,很多代码用到 import json,后来发现ujson性能更高,如果觉得把每个文件的import json 改成 import ujson as json成本较高,或者说想测试一下用ujson替换json是否符合预期,只需要在入口加上:

  1. import json
  2. import ujson
  3. def monkey_patch_json():
  4. json.__name__ = 'ujson'
  5. json.dumps = ujson.dumps
  6. json.loads = ujson.loads
  7. monkey_patch_json()

2、运行时动态增加模块的方法
这种场景也比较多,比如我们引用团队通用库里的一个模块,又想丰富模块的功能,除了继承之外也可以考虑用Monkey Patch。

3、在使用猴子补丁的时候,还应注意如下事项:
  • 基本上只追加功能
  • 进行功能变更时要谨慎,尽可能的小规模
  • 注意相互调用
  • 发表于 2020-01-06 10:54
  • 阅读 ( 466 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1478 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章