1-Monkey Patch

about

Python3.6.8

what's a monkey patch
"monkey patch"一词来自于"guerrilla patch",是杂牌军、游击队的意思,而"guerrilla"的英语发音和"gorllia"大猩猩类似,但大猩猩哪有小猴子讨喜啊,所以,慢慢的"guerrilla patch"就变成了"monkey patch"。

monkey patch的定义
关于"monkey patch"这个术语的定义要取决于使用它的社区。在Ruby、Python和其他的动态编程语言中,"monkey patch"一词仅指在程序运行时,对类或者模块的动态修改或扩展。说白了,"monkey patch"就是在运行时动态的对已有代码进行修改,达到"hot patch"的目的。也可以实现Python中的装饰器的功能,在不修改源码的基础上进行功能扩展。

接下来,演示"monkey patch"在Python中的应用。

动态替换类的方法

如下代码:

class Foo(object):

    def bar(self):
        print("Foo bar method....")

foo = Foo()
foo.bar()
"""运行结果
Foo bar method....
"""

运行结果大家肯定没有异议。
那么现在,有一个更好的new_bar方法替换原来的bar方法,但由于原来的bar被引用的太多,所以,希望不修改原来的代码,就能使用新的new_bar方法,这时候就需要"monkey patch"了:

class Foo(object):

    def bar(self):
        print("Foo bar method....")

    def new_bar(self):
        print("Foo new bar method....")

foo = Foo()
# 使用 monkey patch 思想,偷偷的使用 new_bar 替换到原来的 bar 方法
Foo.bar = Foo.new_bar
# 但调用方式没有改变
foo.bar()
"""运行结果也有了改变
Foo new bar method....
"""

你也可以使用普通的函数来替换原来的bar方法:

class Foo(object):

    def bar(self):
        print("Foo bar method....")

    def new_bar(self):
        print("Foo new bar method....")

def new_bar2(self):
    print("function new bar 2....")


foo = Foo()
# 使用普通的函数替换掉原来的 bar 方法,但 bar 需要 self 参数,new_bar2在定义的时候也需要这个形参
Foo.bar = new_bar2
# 但调用方式没有改变
foo.bar()
"""运行结果也有了改变
function new bar 2....
"""

动态替换模块的方法

这个是"monkey patch"的典型应用场景:

import json
import ujson  # pip install ujson

def monkey_patch_json():
    json.__name__ = 'ujson'
    json.dumps = ujson.dumps
    json.loads = ujson.loads

monkey_patch_json()
s = "abc"

# 这里的json已经被替换为ujson了
print(json.__name__)  # ujson
print(json.dumps(s))  # 调用的方法也被替换为 ujson.dumps 了

动态增加模块的方法

如果要对一个模块进行扩展,但又不修改原模块的内容,"monkey patch"也是一个很好的选择:

import datetime
import arrow  # pip install arrow


now = arrow.now()
# shift 是 arrow 模块的方法
print(now.shift(months=2))  # 获取两个月后的当前时间

# datetime是shift方法的,现在可以通过 monkey patch 的思想,为 datetime 添加一个 shift 方法
datetime.shift = now.shift
print(datetime.shift(months=2))

that's all, see also:

Python Monkey patch猴子补丁 | 常用模块 | http://www.360doc.com/content/19/0527/07/58006001_838437018.shtml | Python Monkey patch猴子补丁 | https://en.wikipedia.org/wiki/Monkey_patch | Pyhon基础:Monkey Patch(猴子补丁) | 猴子补丁(Monkey Patch)

posted @ 2019-02-28 09:58  听雨危楼  阅读(426)  评论(0编辑  收藏  举报