猴子补丁

  1. 在运行时替换方法、属性等,动态属性替换
  2. 在不修改第三方代码的情况下增加原来不支持的功能
  3. 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加
  4. 主要用途在于源码不宜直接修改,而添加补充功能
  5. 例子:python自带的json包不支持自定义对象转json串,在python中用json.dumps转自定义对象时会报异常class is not JSON serializable,通过增加一段代码补丁(称作猴子补丁)便可实现自定义转换,补丁代码如下:
from json import JSONEncoder
"""
自定义_default补丁方法,传入对象
先判断传入的对象中有没有to_json属性,如果没有,则走对象默认的方法,若有则走to_json
"""
def _default(self, obj):
	return getattr(obj.__class__, "to_json", JSONEncoder().default)(obj)
JSONEncoder.default = _default
    
class Tmp:
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def to_json():
        # 返回自定义对象json串
        pass
    

通过补丁代码我们可以看到,代码替换了json包的默认转json的方法,运行了补丁代码后,转json的过程变成了先找对象的to_json属性,在没有to_json属性的情况下才使用默认的JSONEncoder.default的方法,也就是通过这么一个patch,增加了json包原来没有的功能。

import re
old_match = re.match # 保留旧函数,后面可以直接用

def new_match(*args, **kwargs):
    print('re.match is running') # 增加自己的逻辑
    return old_match(*args, **kwargs) # 调用回旧函数

re.match = new_match # 替换掉原来的旧属性(函数)

# 一个全新的函数
def hello(*args, **kwargs):
    print(args, kwargs)
re.hello = hello # 赋予一个新属性(函数)

"""
>>> re.match('.*', 'abc')
re.match is running # 如果没有 patch,此行不会输出
<re.Match object; span=(0, 3), match='abc'>
>>> re.hello(123) # 如果没有 patch,调用这个函数会报错
(123,) {}
"""

猴子补丁与装饰器的区别

作用时期不同:猴子补丁作用于运行时,装饰器作用于定义时

posted @ 2021-09-09 07:57  注入灵魂  阅读(113)  评论(0)    收藏  举报