Python中的猴子补丁
admin
2024-05-21 19:17:50
0

猴子补丁是一项允许在运行时更改对象行为的技术。 它是一个非常有用的功能,但它也可能使你的代码更难以理解和调试,因此,在实现猴子补丁程序时必须谨慎。

猴子补丁的用法

猴子补丁与Python中的灵活性紧密相关。 自定义对象是可变的,因此可以替换其属性而无需创建该对象的新副本。

class A:def speak(self):return "hello"def speak_patch(self):return "world"

我们在最开始的地方做了猴子补丁,即使用speak_patch这个函数去取代掉原来的speak。这时我们调用speak函数就变成了调用speak_patch函数了。

>>> A.speak = speak_patch  # 做了猴子补丁,替换了原来的speak函数
>>> c = A()
>>> c.speak()
world

再来看一个例子:

我们定义一个类,在类中我们不实现__len__方法,而在类外我们实现一个可以计算列表长度的方法。

class A:def __init__(self, array):self._list = array# def __len__(self): #     return len(self._list)def length(obj):return len(obj._list)

下面我们做一个猴子补丁,将类中的__len__方法替换为length函数。

>>> A.__len__ = length
>>> a = A([1, 2, 3])
>>> len(a)
3

注意:该有的参数还是要有,但名称可以不一样,类中原本应该是是self,在类外的实现可以任意写 (例如obj),因为会在做猴子补丁的时候自己去对应起来。但是取长度时,就必须要写obj._list。

可以看到,上面类中并没有定义__len__的方法,但当我们做了猴子补丁以后,仍然可以正确的调用len函数。经过以上的部分,就可以成功的在运行时,实际上实现类中的__len__方法。那为什么不一开始就实现 __len__呢?像是:

class A:def __init__(self, array):self._list = arraydef __len__(self): return len(self._list)

原因是我们不希望去修改类中的源代码,而后者的修改也只是暂时性的,像用在测试时。

当然,猴子补丁不会允许你任意的使用,它是有限制的,它限制你不能给内置类型打补丁。比如要给str这个对象打补丁,就会报错。

>>> def find(self, sub, start=None, end=None):
...     return 'ok'
...>>> str.find = find
Traceback (most recent call last):File "", line 1, in 
TypeError: can't set attributes of built-in/extension type 'str'

这里的原因是可以保证内置的功能都是原本的,避免有人去打补丁后,导致后续一堆奇怪的问题。需要切记,猴子补丁不可乱用!

types.MethodType

很类似猴子补丁,来看一个types.MethodType的例子,

import typesclass A:def speak(self):return "hello"def speak_patch(self):return "world">>> a = A()
>>> a.speak = types.MethodType(speak_patch, a)
>>> a.speak()
'world'
>>> a2 = A()
>>> a2.speak()  # 对于a2我们并没有修改,所以仍然是hello
'hello'

既然提到了types.MethodType,那也就来简单的学一下。

  1. types.MethodType的作用之—:添加实例方法

我们先定义一个类和一个函数

import typesclass cla(object):def __init__(self, name, age):self.name = nameself.age = agedef prii(self):print("pri")def f1(self):print("f1")

我们利用types.MethodType来为类添加实例方法f1。

>>> c = cla("zhangsan", 18)
>>> c.prii()
pri
>>> c.f1 = types.MethodType(f1, c)
>>> c.f1()
f1
>>> func = types.MethodType(f1, c)
>>> func()
f1

可以看到,func()一样可以正常的执行。所以这个动态添加的办法和原生的属性还是有所区别的。执行了types.MethodType(f1,c)之后,相当于产生了一个特殊返回值,这个返回值指向f1函数,里面已经被默认传递了c对象作为参数,只要使用这个返回值,就可以当做是调用了对象的方法。c.f1=types.MethodType(f1,c)这么写之后,再调用c.f1(),完全是为了字面上的符合,符合这个操作的原意而已。

  1. types.MethodType的作用之二:添加静态方法

在使用静态方法时,类中的self将不会再进行传值,此时,静态方法已经和类没什么关系了。 需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数。

还是上面定义的cla类和f1函数,我们接下来定义一个静态方法test。

@staticmethod
def test():print(":static")>>> c = cla("zhangsan", 18)
>>> c.test = test()
>>> c.test()
:static

这里不需要绑定,因为静态方法不需要任何的参数,只要赋值了就直接用。但注意需要使用类名来调用。

  1. types.MethodType的作用之三:添加类方法

下面定义一个类方法clsm,类方法也是直接赋值调用就行。

@classmethod
def clsm(cls):print("classmethod call")>>> cla.clsm = clsm
>>> cla.clsm()
classmethod call

动态添加可以做到什么呢?一款APP,在没有进行整个APP的情况下,里面的部分功能变了。即我部分的功能代码存在一个文件中,我在后台默默更换这些文件,下次你再打开APP,对应的功能或者样式就变了。这是不是就是类似猴子补丁呢?

什么时候用去猴子补丁?

猴子补丁非常强大,它显示了Python的灵活性。下面就来思考一下何时用猴子补丁。

作为一般规则,最好不要打猴子补丁。例如,如果要更改程序的行为,则可以为要更改的类定义子类。猴子补丁的问题在于程序的行为变得更加难以理解,要追溯行为的变化变得非常复杂。但是,有时可能会有很大的好处。例如,使用numpy计算快速傅里叶变换可能比使用其他实现慢。想象一下你想使用PyFFTW,但是不想重写所有程序。这时你可以猴子补丁你的代码!

请参阅下面的示例:

import pyfftw
import numpy
numpy.fft = pyfftw.interfaces.numpy_fft

现在,无论何时使用numpy提供的FFT例程,它们都会被PyFFTW的例程自动替换。这可能会对你的程序产生巨大的影响,并且只用了一行代码!

另外,常见的情况是测试。有时,你想在缺乏某些功能的环境中测试代码,或者由于测试实际上是在修改实时数据库,因此想防止这种情况。在这种情况下,可以在进行测试之前更改与数据库通信的方法。 即在测试程序时先避免与设备通信。

总之,究竟如何实现此行为将取决于具体情况。

相关内容

热门资讯

17.18岁的小男孩适合做什么... 17.18岁的小男孩适合做什么工作,最好是可以边学点技术的?17岁的话,也就差不多初中刚毕业的年龄,...
三国争霸锦囊道具 三国争霸锦囊道具我想知道起凡三国争霸里所有锦囊能开出来的但在店里买不到的装备属性分别介绍要全面哦烈4...
敬谢不敏是什么意思 ? 敬谢不敏是什么意思 ?敬谢不敏,谢:推辞;不敏:不聪明,没有才能。恭敬地表示自己能力不足,不能够接受...
拿刀割脚是什么成语 拿刀割脚是什么成语成语有“削足适履”,鞋小了,拿刀把脚去一点,以适合穿上,形容主次颠倒,应该是由鞋去...
“云上那达慕”开启百里荒帐篷露... 搜狐号消息 记者 项俊平 武汉报道 草地上摔跤,马背上夺羊......7月12日,随着“云上那达慕盛...
淅川:露营音乐季引爆夏日旅游热... 河南日报社三农全媒体中心记者 曹怡然 见习记者 高磊 通讯员 李金杭 7月12日,淅川县毛堂乡龙腾松...
谐音故事的简介 谐音故事的简介 谐音故事:在作文中使用时,会给大家带来幽默感。
如果有人统一四大基本力,那么他... 如果有人统一四大基本力,那么他在科学界是不是最伟大的?统一四大晌明基本力的人是科学界最伟大的。目前还...
我是深圳小主人(大运会的) 我是深圳小主人(大运会的)字不要太多、100—50就行了少时诵诗书少时诵诗书做大运小主人大事小事天下...
像"完壁归赵&quo... 像"完壁归赵"这样的历史故事成语还有吗?要带上作者!作业啊``烦死了!!三顾茅庐 刘备
各位书迷帮忙推荐几本好看的小说 各位书迷帮忙推荐几本好看的小说恶魔法则盘龙斗罗大陆好,来点大气的,《三生三世十里桃花》《醉玲珑》《薄...
梦星辰的含义? 梦星辰的含义?梦到了星辰 东方尚英 ( 回答 )
如果一个男生说分手了,是不是真... 如果一个男生说分手了,是不是真的不爱了?是的,因为如果真的喜欢一个人,是不会轻易说分手的,说了分手就...
在明代兵器之中,火器在当时的世... 在明代兵器之中,火器在当时的世界上是最领先的水平吗?明代火器在当时世界上到底有多历害?算是吧,明朝那...
与君初相识是三生三世十里桃花续... 与君初相识是三生三世十里桃花续写吗不是。与君初相识和三生三世十里桃花都是仙侠剧,但是构思和世界观都不...
电视剧宫和步步惊心哪个比较好看... 电视剧宫和步步惊心哪个比较好看!如果你喜欢看《流星花园》就看《宫》剧情方面:同样都是“九子夺嫡”的清...
你们上学的时候都发生过哪些有趣... 你们上学的时候都发生过哪些有趣的事吗?记得我上小学的时候特别的贪玩。记得一次玩得特别累特别晚才去睡觉...
小女孩喜欢什么礼物 小女孩喜欢什么礼物迷你厨房。女孩子对做饭比较喜欢,我家的孩子就天天拿着饭盒、勺子等学做饭、炒菜,于是...
急求酒店管理 暑期实习日志8篇 急求酒店管理 暑期实习日志8篇可以找个酒店去实习一下
口袋妖怪黑白攻略 口袋妖怪黑白攻略我的是日文,我想要个攻略照着玩可以参考口袋吧资料库,绝对完整准确