IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python中的Monkey Patch(猴子补丁) -> 正文阅读

[Python知识库]Python中的Monkey Patch(猴子补丁)

一、猴子补丁的介绍

关于猴子补丁为啥叫猴子补丁,据说是这样子的:

这个叫法起源于Zope框架,大家在修正Zope的Bug的时候经常在程序后面追加更新部分,这些被称作是“杂牌军补丁(guerilla patch)”,后来guerilla就渐渐的写成了gorllia((猩猩),再后来就写了monkey(猴子),所以猴子补丁的叫法是这么莫名其妙的得来的。

Monkey Patch的翻译叫“程序运行过程中的补丁”?

二、什么时候用到

如果都是自己写的代码,Monkey Patch 就毫无意义了,直接改源码就可以。Monkey Patch 的主要用途,在于源码不宜直接修改。比如你要修正一个第三方 module 的 bug 或者进行特定的修正、扩展,通常来说有下面几种做法:

1.直接把源?package/module,复制一份到当前项目中,再改源码;但不推荐,因为会导致当前的项目代码管理上的混乱。

2.向源作者提 pull request,以修正 bug 或者其他;应该如此,但未必能联系到对方,联系到了对方未必修改,修改了未必很快能用上。

这个时候 Monkey Patch 的价值就出来了,不用改原始的 module 源码,就能达到自己期望的效果。

三、如何打补丁

当前Python版本为3.8.3,以下为打补丁的简单示例:

import re

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

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

# 一个全新的函数
def hello(*args, **kwargs):
    print(args, kwargs)

re.match = new_match # 替换掉原来的旧属性(函数)
re.hello = hello # 赋予一个新属性(函数)
re.match(".*", "abc")
re.hello(123, 456)

执行上述代码,输出结果为:

re.match is running
(123, 456) {}

再看另外一个案例:例如当前有一个类Foo,我们想使用json对该类的实例化对象foo进行序列化

import json

class Foo(object):
    def __init__(self, name):
        self.name = name

foo = Foo("orange")
print(json.dumps(foo))

?执行上述代码,其输出结果为:

  File "d:\python3.8\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Foo is not JSON serializable

从上述结果中可以看到Python自带的json包不支持自定义对象转json串,在Python中用json.dumps转自定义对象时会报异常class?is?not?JSON?serializable。这个时候我们可以通过增加一段补丁代码(猴子补丁)便可实现自定义转换,首先创建一个名为make_json_serializable.py的文件,里面的补丁内容如下:

import json

def _default(self, obj):
    return getattr(obj.__class__, "to_json", _default.default)(obj)

_default.default = json.JSONEncoder.default  # Save unmodified default.
json.JSONEncoder.default = _default  # Replace it.

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

在另外一个xxx.py文件中导入make_json_serializable,然后再使用json进行序列化:

import json
import make_json_serializable

class Foo(object):
    def __init__(self, name):
        self.name = name

    def to_json(self):  # New special method.
        """ Convert to JSON format string representation. """
        return '{"name": "%s"}' % self.name

foo = Foo("orange")
print(json.dumps(foo))

输出结果:

"{\"name\": \"orange\"}"

总结:实际使用猴子补丁时,一般会把需要 patch(打补丁)?的逻辑,放在一个多个(归属同一个模块文件夹)?.py?文件内,然后在主要.py 文件?头部进行一次import,这样就实现了全局的 Monkey Patch了。

四、猴子补丁的用处

1.在运行时替换方法、属性等
2.在不修改第三方代码的情况下增加原来不支持的功能
3.在运行时为内存中的对象增加patch(补丁)而不是在磁盘的源代码中增加

例如:上面自定义对象转json,在原有json包不满足的条件下,只需要将以上的一个patch写在一个文件里自己再import一次,便可实现自己想要的功能,这是非常方便的。

猴子补丁的主要功能便是在不去改变源码的情况下而对功能进行追加和变更,对于编程过程中使用一些第三方不满足需求的情况下,使用猴子补丁是非常方便的。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:27:16  更:2022-03-10 22:28:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:28:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码