python中的猴子补丁

猴子补丁的定义

所谓猴子补丁,即不在源码中进行改动,而是在代码运行时改动的类或模块

示例

我们新建两个类,一个猴子类和一个猴群类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Monkey:
'''
猴子类
'''
def __init__(self,name):
self.name = name
class Monkeys:
'''
猴群
'''
_monkeys = []
def __init__(self,monkeys):
self._monkeys = monkeys
def __getitem__(self,position):
return self._monkeys[position]
def __len__(self):
return len(self._monkeys)
def __repr__(self):
return "<monkeys {}>".format(','.join((m.name for m in self)))

由定义可以看出,猴群类实现了序列协议,支持下标取值和长度判断。
接下来创建5个猴子,并让他们按顺序排好队:

1
2
3
4
5
6
7
8
9
10
11
m1 = Monkey("猴1")
m2 = Monkey("猴2")
m3 = Monkey("猴3")
m4 = Monkey("猴4")
m5 = Monkey("猴5")
monkeys = Monkeys([m1,m2,m3,m4,m5])
print(monkeys)
--------------
<monkeys 猴1,猴2,猴3,猴4,猴5>

现在我们想要将其顺序打乱,shuffle一下看看:

1
2
3
4
5
6
7
8
9
10
from random import shuffle
shuffle(monkeys) #不支持打乱
---------------
Traceback (most recent call last):
File "pythonscripts/mokey_patch.py", line 47, in <module>
shuffle(monkeys) #不支持打乱
File "/usr/lib/python3.5/random.py", line 272, in shuffle
x[i], x[j] = x[j], x[i]
TypeError: 'Monkeys' object does not support item assignmen

猴群不支持打乱的原因是因为Monkeys类并没有实现setitem方法,接下来,我们利用猴子补丁,给猴群添加打乱的功能:

1
2
3
4
5
6
7
8
9
def set_monkey(monkeys,position,monkey):
monkeys._monkeys[position] = monkey
Monkeys.__setitem__ = set_monkey
shuffle(monkeys)
print(monkeys)
--------------
<monkeys 猴1,猴5,猴4,猴2,猴3>

这里猴群已经被打乱了,而且我们并没有改动源码,只是在代码运行中给Monkey类添加了setitem方法,这就是猴子补丁的作用。