猴子補(bǔ)丁(monkey patch)

寫了一段時間java切回寫python偶爾會出現(xiàn)一些小麻煩螟凭,比如:在java中自定義對象變成json串很簡單,調(diào)用一個方法就行它呀,但同樣的轉(zhuǎn)換在python中卻不太容易實現(xiàn)螺男。在尋找python自定義對象轉(zhuǎn)json串的過程中,接觸到了猴子補(bǔ)丁這個東西纵穿,感覺還有點意思下隧;本文先實現(xiàn)python自定義對象轉(zhuǎn)json串,再簡單談一下猴子補(bǔ)丁谓媒。

python自定義對象轉(zhuǎn)json串

python自帶的json包不支持自定義對象轉(zhuǎn)json串淆院,在python中用json.dumps轉(zhuǎn)自定義對象時會報異常class is not JSON serializable,通過增加一段代碼補(bǔ)毒涔摺(稱作猴子補(bǔ)锻帘纭)便可實現(xiàn)自定義轉(zhuǎn)換,補(bǔ)丁代碼如下:

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

最后保證補(bǔ)丁代碼在自定義對象轉(zhuǎn)json之前執(zhí)行過一次即可拷淘。

通過補(bǔ)丁代碼我們可以看到,代碼替換了json包的默認(rèn)轉(zhuǎn)json的方法蒙保,運行了補(bǔ)丁代碼后辕棚,轉(zhuǎn)json的過程變成了先找對象的to_json屬性,在沒有to_json屬性的情況下才使用默認(rèn)的JSONEncoder.default的方法邓厕,也就是通過這么一個patch逝嚎,增加了json包原來沒有的功能。

猴子補(bǔ)丁

關(guān)于猴子補(bǔ)丁為啥叫猴子補(bǔ)丁详恼,據(jù)說是這樣子的:

這個叫法起源于Zope框架补君,大家在修正Zope的Bug的時候經(jīng)常在程序后面追加更新部分,這些被稱作是“雜牌軍補(bǔ)丁(guerilla patch)”昧互,后來guerilla就漸漸的寫成了gorllia((猩猩)挽铁,再后來就寫了monkey(猴子),所以猴子補(bǔ)丁的叫法是這么莫名其妙的得來的敞掘。

猴子補(bǔ)丁主要有以下幾個用處:

  1. 在運行時替換方法叽掘、屬性等
  2. 在不修改第三方代碼的情況下增加原來不支持的功能
  3. 在運行時為內(nèi)存中的對象增加patch而不是在磁盤的源代碼中增加

例如:上面自定義對象轉(zhuǎn)json,在原有json包不滿足的條件下玖雁,只需要將以上的一個patch寫在一個文件里自己再import一次更扁,便可實現(xiàn)自己想要的功能,這是非常方便的。

可以知道猴子補(bǔ)丁的主要功能便是在不去改變源碼的情況下而對功能進(jìn)行追加和變更浓镜;對于編程過程中使用一些第三方不滿足需求的情況下溃列,使用猴子補(bǔ)丁是非常方便的。

猴子補(bǔ)丁膛薛,算是編程中的一個技巧了听隐。

拓展

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]'
'''
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椿访,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子虑润,更是在濱河造成了極大的恐慌,老刑警劉巖加酵,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拳喻,死亡現(xiàn)場離奇詭異,居然都是意外死亡猪腕,警方通過查閱死者的電腦和手機(jī)冗澈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陋葡,“玉大人亚亲,你說我怎么就攤上這事「停” “怎么了捌归?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岭粤。 經(jīng)常有香客問我惜索,道長,這世上最難降的妖魔是什么剃浇? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任巾兆,我火速辦了婚禮,結(jié)果婚禮上虎囚,老公的妹妹穿的比我還像新娘角塑。我一直安慰自己,他們只是感情好淘讥,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布圃伶。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪留攒。 梳的紋絲不亂的頭發(fā)上煤惩,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音炼邀,去河邊找鬼魄揉。 笑死,一個胖子當(dāng)著我的面吹牛拭宁,可吹牛的內(nèi)容都是我干的洛退。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼杰标,長吁一口氣:“原來是場噩夢啊……” “哼兵怯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腔剂,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤媒区,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后掸犬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袜漩,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年湾碎,在試婚紗的時候發(fā)現(xiàn)自己被綠了宙攻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡介褥,死狀恐怖座掘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柔滔,我是刑警寧澤溢陪,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站廊遍,受9級特大地震影響嬉愧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喉前,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一没酣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卵迂,春花似錦裕便、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春下翎,著一層夾襖步出監(jiān)牢的瞬間缤言,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工视事, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留胆萧,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓俐东,卻偏偏與公主長得像跌穗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虏辫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,756評論 25 707
  • 一蚌吸、學(xué)習(xí)任務(wù) 英語 記背單詞 新65 舊58 何凱文每日一句更新 二、日常生活 早上起來媽媽就回來了砌庄,然后我...
    狂野的孩兒也狂野閱讀 228評論 0 0
  • 機(jī)場的旺季隨著夏季一同到來羹唠,這里不僅有氣溫的上升,還有旅客的增多和航班的增加娄昆,隨之而來的就是貨運部整個部門工作強(qiáng)度...
    我是我自己的驕傲閱讀 326評論 1 2
  • 魯迅說:所謂悲劇就是把美好的東西打破給人看肉迫。在人生旅途中,自己把握不住自己的命運稿黄,白了少年頭,空悲切跌造! 陸游二十...
    楊杰子江閱讀 468評論 1 3
  • 你的眼睛是否鑲嵌了寶石 才會讓我愛你如此瘋狂 是否瘋狂杆怕,才會更了解你 或許只是你的臉 才讓我想去吻 或許就是那些日...
    信仰_5fd8閱讀 308評論 0 0