一.什么是猴子补丁?

  属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。
  猴子补丁的核心就是用自己的代码替换所用模块的源代码,详细地如下

  1,这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。
  2,还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。

二. 猴子补丁的功能(一切皆对象)

  1.拥有在模块运行时替换的功能, 例如: 一个函数对象赋值给另外一个函数对象(把函数原本的执行的功能给替换了)

class Monkey:
	def hello(self):
		print('hello')

def world(self):
	print('world')


def other_func():
	print("from other_func")



monkey = Monkey()
monkey.hello = monkey.world
monkey.hello()
monkey.world = other_func
monkey.world()

三.monkey patch的应用场景

如果我们的程序中已经基于json模块编写了大量代码了,发现有一个模块ujson比它性能更高,
但用法一样,我们肯定不会想所有的代码都换成ujson.dumps或者ujson.loads,那我们可能
会想到这么做
import ujson as json
但是这么做的需要每个文件都重新导入一下,维护成本依然很高
此时我们就可以用到猴子补丁了
只需要在入口加上:

import json
import ujson

def monkey_patch_json():
    json.__name__ = 'ujson'
    json.dumps = ujson.dumps
    json.loads = ujson.loads

monkey_patch_json() # 之所以在入口处加,是因为模块在导入一次后,后续的导入便直接引用第一次的成果

#其实这种场景也比较多, 比如我们引用团队通用库里的一个模块, 又想丰富模块的功能, 除了继承之外也可以考虑用Monkey
Patch.采用猴子补丁之后,如果发现ujson不符合预期,那也可以快速撤掉补丁。个人感觉Monkey
Patch带了便利的同时也有搞乱源代码的风险!