ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python笔记69 - 什么是猴子补丁(Monkey Patch)?

2021-11-22 13:02:11  阅读:144  来源: 互联网

标签:obj Monkey python self Patch json import def name


前言

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安装的时候,就忘记之前改哪里了)
像这种情况下,可以自己写个方法去替换第三方包原来的方法,非常实用!

标签:obj,Monkey,python,self,Patch,json,import,def,name
来源: https://www.cnblogs.com/yoyoketang/p/15588036.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有