這篇文章將為大家詳細(xì)講解有關(guān)python中monkey patch有什么用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
成都創(chuàng)新互聯(lián)公司是一家專業(yè)的成都網(wǎng)站建設(shè)公司,我們專注成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷、企業(yè)網(wǎng)站建設(shè),買鏈接,1元廣告為企業(yè)客戶提供一站式建站解決方案,能帶給客戶新的互聯(lián)網(wǎng)理念。從網(wǎng)站結(jié)構(gòu)的規(guī)劃UI設(shè)計到用戶體驗提高,創(chuàng)新互聯(lián)力求做到盡善盡美。python自定義對象轉(zhuǎn)json串
python自帶的json包不支持自定義對象轉(zhuǎn)json串,在python中用json.dumps轉(zhuǎn)自定義對象時會報異常class is not JSON serializable,通過增加一段代碼補?。ǚQ作猴子補丁)便可實現(xiàn)自定義轉(zhuǎn)換,補丁代碼如下:
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
同時在自定義對象里面實現(xiàn)to_json方法。
class Tmp: def __init__(self, id, name): self.id = id self.name = name def to_json(): # 返回自定義對象json串 pass
最后保證補丁代碼在自定義對象轉(zhuǎn)json之前執(zhí)行過一次即可。
通過補丁代碼我們可以看到,代碼替換了json包的默認(rèn)轉(zhuǎn)json的方法,運行了補丁代碼后,轉(zhuǎn)json的過程變成了先找對象的to_json屬性,在沒有to_json屬性的情況下才使用默認(rèn)的JSONEncoder.default的方法,也就是通過這么一個patch,增加了json包原來沒有的功能。
猴子補丁
關(guān)于猴子補丁為啥叫猴子補丁,據(jù)說是這樣子的:
這個叫法起源于Zope框架,大家在修正Zope的Bug的時候經(jīng)常在程序后面追加更新部分,這些被稱作是“雜牌軍補丁(guerilla patch)”,后來guerilla就漸漸的寫成了gorllia((猩猩),再后來就寫了monkey(猴子),所以猴子補丁的叫法是這么莫名其妙的得來的。
猴子補丁主要有以下幾個用處:
在運行時替換方法、屬性等
在不修改第三方代碼的情況下增加原來不支持的功能
在運行時為內(nèi)存中的對象增加patch而不是在磁盤的源代碼中增加
例如:上面自定義對象轉(zhuǎn)json,在原有json包不滿足的條件下,只需要將以上的一個patch寫在一個文件里自己再import一次,便可實現(xiàn)自己想要的功能,這是非常方便的。
可以知道猴子補丁的主要功能便是在不去改變源碼的情況下而對功能進行追加和變更;對于編程過程中使用一些第三方不滿足需求的情況下,使用猴子補丁是非常方便的。
猴子補丁,算是編程中的一個技巧了。
拓展
json包默認(rèn)轉(zhuǎn)json的過程
可以看一下json包里面轉(zhuǎn)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,將所有的自建對象都匹配一遍,最后匹配不到的就報錯了,所以自定義對象轉(zhuǎn)json自然會有問題。
其他實現(xiàn)自定義對象轉(zhuǎn)json的方法
其實json包的源碼文檔里面也有很詳細(xì)的別的自定義對象轉(zhuǎn)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]' '''
關(guān)于“python中monkey patch有什么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。