python笔记69 - 什么是猴子补丁(Monkey Patch)?
前言
python里面什么是猴子补丁(Monkey Patch)?,使用场景有哪些? 猴子补丁主要有以下几个用处:
- 在运行时替换方法、属性等
- 在不修改第三方代码的情况下增加原来不支持的功能
- 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
猴子补丁(Monkey Patch)
属性在运行时的动态替换,叫做猴子补丁(Monkey Patch)。 作用是在运行的时候,动态替换模块方法。先看一个简单的例子 如果有一个模块somemodule.py,在其它代码里面有用到这个类里面的speak方法
class SomeClass(object):
def __init__(self):
self.name = "yoyo"
def speak(self):
return "hello world"
在不改变原来代码的基础上,可以重新定义一个speck方法,替换原来的
from xxx.somemodule import SomeClass
def new_speak(self):
return "new hello"
# 替换speck方法
SomeClass.speak = new_speak
替换之后,调用的时候,就会变成新的方法里面内容
some = SomeClass()
print(some.speak())
# 运行结果 new hello
python自定义对象转json串
我自己定义了一个类,如下
class MyDefined(object):
def __init__(self):
self.name = "yoyo"
self.age = 18
def __repr__(self):
return 'name={}&age={}'.format(self.name, self.age)
在定义字典的时候,引用了上面类的实例
aa = {
"a1": True,
"b1": "hello",
"c1": [1, 2, 3],
"d1": MyDefined()
}
print(aa)
# 运行结果:{'a1': True, 'b1': 'hello', 'c1': [1, 2, 3], 'd1': name=yoyo&age=18}
如果直接转json串,会出现异常:TypeError: Object of type ‘MyDefined’ is not JSON serializable
import json
print(json.dumps(aa))
因为MyDefined类是我自己定义的,json库无法解析成对应的字符串,这种情况就需要自己去写一个解析方式
方法一:可以在json.dumps 传一个cls参数
import json
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, MyDefined):
return str(obj)
else:
return json.JSONEncoder.default(self, obj)
print(json.dumps(aa, cls=MyEncoder))
# 运行结果 {"a1": true, "b1": "hello", "c1": [1, 2, 3], "d1": "name=yoyo&age=18"}
方法二:使用猴子补丁来解决
from json import JSONEncoder
def new_default(self, obj):
if isinstance(obj, MyDefined):
return str(obj)
else:
return json.JSONEncoder.default(self, obj)
JSONEncoder.default = new_default
print(json.dumps(aa))
# 运行结果 {"a1": true, "b1": "hello", "c1": [1, 2, 3], "d1": "name=yoyo&age=18"}
替换模块
还有一个比较实用的例子,很多代码用到 import json,后来发现ujson性能更高, 如果觉得把每个文件的import json 改成 import ujson as json成本较高,或者说想测试一下用ujson替换json是否符合预期,只需要在入口加上:
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
monkey_patch_json()
运行中替换或者添加方法是非常有用的,比如说在单元测试中,有些负责和外界服务通信的函数就需要替换掉,方便测试。 这个技巧不仅很常用,而且在你最终决定要修改代码之前还可以保持代码的可维护性,是一个非常重要的技巧。 还有比如你在pip安装第三方包的时候,使用过程中发现某个方法有一些bug,或者不兼容中文的情况,这时候不要去改源码(虽然改源码能解决,但不利于后期维护,后期你换个电脑,重新pip安装的时候,就忘记之前改哪里了) 像这种情况下,可以自己写个方法去替换第三方包原来的方法,非常实用!
相关文章
- Python中的函数与方法 以及Bound Method和Unbound Method
- 一文贯通python文件读取
- Python 中的异步编程:Asyncio
- 7个你现在就该学习Python的理由
- 提高Python运行效率的六个窍门
- Python数据科学:神经网络
- 一篇文章看懂大数据分析就业前景及职能定位
- R和Python中的文本挖掘:8个入门小贴士
- 告诉你为什么Python有点慢,但我却无所谓?
- 专注学习DevOps编程语言Top 5推荐
- Python发送邮件脚本
- Python多进程并行编程实践: mpi4py 的使用
- Python语言在未来的发展前景
- Python vs Ruby: 谁是最好的 web 开发语言?
- Python对Ruby:谁在Web开发领域更胜一筹?
- Python一行代码完成并行任务
- Python开发者2017应该关注的七个类库
- python爬虫入门基本知识
- 在终端中优雅地编写Python
- Python机器学习实战:信用卡欺诈检测