python 猴子补丁(monkey patch)

作者:d咚咚呛 时间:2022-12-25 02:15:13 

写了一段时间java切回写python偶尔会出现一些小麻烦,比如:在java中自定义对象变成json串很简单,调用一个方法就行,但同样的转换在python中却不太容易实现。在寻找python自定义对象转json串的过程中,接触到了猴子补丁这个东西,感觉还有点意思;本文先实现python自定义对象转json串,再简单谈一下猴子补丁。

python自定义对象转json串

python自带的json包不支持自定义对象转json串,在python中用json.dumps转自定义对象时会报异常class is not JSON serializable,通过增加一段代码补丁(称作猴子补丁)便可实现自定义转换,补丁代码如下:


from json import JSONEncoder
 def _default(self, obj):
   return getattr(obj.__class__, "to_json", _default.default)(obj)
 _default.default = JSONEncoder().default
 default.JSONEncoder.default = _default

同时在自定义对象里面实现to_json方法。


class Tmp:
 def __init__(self, id, name):
   self.id = id
   self.name = name

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

最后保证补丁代码在自定义对象转json之前执行过一次即可。

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

猴子补丁

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

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

猴子补丁主要有以下几个用处:

  • 在运行时替换方法、属性等

  • 在不修改第三方代码的情况下增加原来不支持的功能

  • 在运行时为内存中的对象增加patch而不是在磁盘的源代码中增加

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

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

猴子补丁,算是编程中的一个技巧了。

拓展

json包默认转json的过程

可以看一下json包里面转json串的过程:


def _iterencode(o, _current_indent_level):
   if isinstance(o, basestring):
     yield _encoder(o)
   elif o is None:
     yield 'null'
   elif o is True:
     yield 'true'
   elif o is False:
     yield 'false'
   elif isinstance(o, (int, long)):
     yield str(o)
   elif isinstance(o, float):
     yield _floatstr(o)
   elif isinstance(o, (list, tuple)):
     for chunk in _iterencode_list(o, _current_indent_level):
       yield chunk
   elif isinstance(o, dict):
     for chunk in _iterencode_dict(o, _current_indent_level):
       yield chunk
   else:
     if markers is not None:
       markerid = id(o)
       if markerid in markers:
         raise ValueError("Circular reference detected")
       markers[markerid] = o
     o = _default(o)
     for chunk in _iterencode(o, _current_indent_level):
       yield chunk
     if markers is not None:
       del markers[markerid]

其实就是一连串的if-elif-else,将所有的自建对象都匹配一遍,最后匹配不到的就报错了,所以自定义对象转json自然会有问题。

其他实现自定义对象转json的方法

其实json包的源码文档里面也有很详细的别的自定义对象转json的方法。


r'''
Specializing JSON object decoding::

>>> import json
 >>> def as_complex(dct):
 ...   if '__complex__' in dct:
 ...     return complex(dct['real'], dct['imag'])
 ...   return dct
 ...
 >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
 ...   object_hook=as_complex)
 (1+2j)
 >>> from decimal import Decimal
 >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1')
 True

Specializing JSON object encoding::

>>> import json
 >>> def encode_complex(obj):
 ...   if isinstance(obj, complex):
 ...     return [obj.real, obj.imag]
 ...   raise TypeError(repr(o) + " is not JSON serializable")
 ...
 >>> json.dumps(2 + 1j, default=encode_complex)
 '[2.0, 1.0]'
 >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
 '[2.0, 1.0]'
 >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
 '[2.0, 1.0]'
'''

来源:https://www.jianshu.com/p/f1060b22aab8

标签:python,猴子补丁
0
投稿

猜你喜欢

  • Javascript的时间戳和php的时间戳转换注意事项

    2023-11-19 16:12:30
  • numpy ndarray 按条件筛选数组,关联筛选的例子

    2021-04-12 04:58:09
  • 将tensorflow模型打包成PB文件及PB文件读取方式

    2022-07-02 22:47:33
  • sqlserver合并DataTable并排除重复数据的通用方法分享

    2012-01-05 18:59:56
  • 基于php解决json_encode中文UNICODE转码问题

    2023-07-02 20:51:22
  • Python tkinter 列表框Listbox属性详情

    2023-09-16 14:06:26
  • Oracle中大批量删除数据的方法

    2010-07-21 13:05:00
  • Python实现按照指定要求逆序输出一个数字的方法

    2023-12-21 23:37:46
  • Python使用import导入本地脚本及导入模块的技巧总结

    2022-09-07 15:09:29
  • php下intval()和(int)转换使用与区别

    2023-06-11 14:09:54
  • 基于python实现数组格式参数加密计算

    2021-08-20 23:29:54
  • 详解如何利用Python制作24点小游戏

    2022-02-04 17:22:42
  • python使用jieba实现中文分词去停用词方法示例

    2021-02-04 11:27:17
  • Python实现提取Excel指定关键词的行数据

    2022-09-01 10:15:59
  • python实现用户登录系统

    2023-10-13 13:17:22
  • python matplotlib绘图实现删除重复冗余图例的操作

    2023-11-02 22:36:44
  • asp正则表达式在网页处理中的应用四则

    2008-02-24 14:44:00
  • python服务器与android客户端socket通信实例

    2022-04-28 02:30:31
  • Python numpy大矩阵运算内存不足如何解决

    2022-08-06 22:38:21
  • 使用tensorflow实现AlexNet

    2023-08-10 08:29:30
  • asp之家 网络编程 m.aspxhome.com