python猴⼦补丁(monkeypatch)
写了⼀段时间java切回写python偶尔会出现⼀些⼩⿇烦,⽐如:在java中⾃定义对象变成json串很简单,调⽤⼀个⽅法就⾏,
但同样的转换在python中却不太容易实现。在寻找python⾃定义对象转json串的过程中,接触到了猴⼦补丁这个东西,感觉还
有点意思;本⽂先实现python⾃定义对象转json串,再简单谈⼀下猴⼦补丁。
python⾃定义对象转json串
python⾃带的json包不⽀持⾃定义对象转json串,在python中⽤转⾃定义对象时会报异常classisnotJSON
rializable,通过增加⼀段代码补丁(称作猴⼦补丁)便可实现⾃定义转换,补丁代码如下:
fromjsonimportJSONEncoder
def_default(lf,obj):
returngetattr(obj.__class__,"to_json",_t)(obj)
_t=JSONEncoder().default
t=_default
同时在⾃定义对象⾥⾯实现to_json⽅法。
classTmp:
def__init__(lf,id,name):
=id
=name
defto_json():
#返回⾃定义对象json串
pass
最后保证补丁代码在⾃定义对象转json之前执⾏过⼀次即可。
通过补丁代码我们可以看到,代码替换了json包的默认转json的⽅法,运⾏了补丁代码后,转json的过程变成了先找对象的
to_json属性,在没有to_json属性的情况下才使⽤默认的t的⽅法,也就是通过这么⼀个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):
ifisinstance(o,bastring):
yield_encoder(o)
elifoisNone:
yield'null'
elifoisTrue:
yield'true'
elifoisFal:
yield'fal'
elifisinstance(o,(int,long)):
yieldstr(o)
elifisinstance(o,float):
yield_floatstr(o)
elifisinstance(o,(list,tuple)):
forchunkin_iterencode_list(o,_current_indent_level):
yieldchunk
elifisinstance(o,dict):
forchunkin_iterencode_dict(o,_current_indent_level):
yieldchunk
el:
ifmarkersisnotNone:
markerid=id(o)
ifmarkeridinmarkers:
raiValueError("Circularreferencedetected")
markers[markerid]=o
o=_default(o)
forchunkin_iterencode(o,_current_indent_level):
yieldchunk
ifmarkersisnotNone:
delmarkers[markerid]
其实就是⼀连串的if-elif-el,将所有的⾃建对象都匹配⼀遍,最后匹配不到的就报错了,所以⾃定义对象转json⾃然会有问
题。
其他实现⾃定义对象转json的⽅法
其实json包的源码⽂档⾥⾯也有很详细的别的⾃定义对象转json的⽅法。
r'''
SpecializingJSONobjectdecoding::
>>>importjson
>>>defas_complex(dct):
...if'__complex__'indct:
...returncomplex(dct['real'],dct['imag'])
...returndct
...
>>>('{"__complex__":true,"real":1,"imag":2}',
...object_hook=as_complex)
(1+2j)
>>>fromdecimalimportDecimal
>>>('1.1',par_float=Decimal)==Decimal('1.1')
True
SpecializingJSONobjectencoding::
>>>importjson
>>>defencode_complex(obj):
...ifisinstance(obj,complex):
...return[,]
...raiTypeError(repr(o)+"isnotJSONrializable")
...
>>>(2+1j,default=encode_complex)
'[2.0,1.0]'
>>>coder(default=encode_complex).encode(2+1j)
'[2.0,1.0]'
>>>''.join(coder(default=encode_complex).iterencode(2+1j))
'[2.0,1.0]'
'''
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
本文发布于:2022-12-28 12:15:31,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/46568.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |