猴子在 Python 中的另一个模块中修补类 [英] Monkey patching a class in another module in Python

查看:28
本文介绍了猴子在 Python 中的另一个模块中修补类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用其他人编写的模块.我想修补模块中定义的类的 __init__ 方法.我发现的展示如何执行此操作的示例都假设我会自己调用该类(例如 Monkey-patch Python 类).然而,这种情况并非如此.在我的情况下,该类是在另一个模块的函数中初始化的.请参阅下面的(大大简化的)示例:

I'm working with a module written by someone else. I'd like to monkey patch the __init__ method of a class defined in the module. The examples I have found showing how to do this have all assumed I'd be calling the class myself (e.g. Monkey-patch Python class). However, this is not the case. In my case the class is initalised within a function in another module. See the (greatly simplified) example below:

thirdpartymodule_a.py

class SomeClass(object):
    def __init__(self):
        self.a = 42
    def show(self):
        print self.a

thirdpartymodule_b.py

import thirdpartymodule_a
def dosomething():
    sc = thirdpartymodule_a.SomeClass()
    sc.show()

mymodule.py

import thirdpartymodule_b
thirdpartymodule_b.dosomething()

有什么办法可以修改SomeClass__init__方法,这样当dosomething从mymodule.py被调用时,例如,打印 43 而不是 42?理想情况下,我可以包装现有的方法.

Is there any way to modify the __init__ method of SomeClass so that when dosomething is called from mymodule.py it, for example, prints 43 instead of 42? Ideally I'd be able to wrap the existing method.

我无法更改第三方模块*.py 文件,因为其他脚本依赖于现有功能.我宁愿不必创建自己的模块副本,因为我需要进行的更改非常简单.

I can't change the thirdpartymodule*.py files, as other scripts depend on the existing functionality. I'd rather not have to create my own copy of the module, as the change I need to make is very simple.

编辑 2013-10-24

我在上面的例子中忽略了一个很小但很重要的细节.SomeClassthirdpartymodule_b 导入,如下所示:from thirdpartymodule_a import SomeClass.

I overlooked a small but important detail in the example above. SomeClass is imported by thirdpartymodule_b like this: from thirdpartymodule_a import SomeClass.

要执行 F.J 建议的补丁,我需要替换 thirdpartymodule_b 中的副本,而不是 thirdpartymodule_a.例如thirdpartymodule_b.SomeClass.__init__ = new_init.

To do the patch suggested by F.J I need to replace the copy in thirdpartymodule_b, rather than thirdpartymodule_a. e.g. thirdpartymodule_b.SomeClass.__init__ = new_init.

推荐答案

以下应该有效:

import thirdpartymodule_a
import thirdpartymodule_b

def new_init(self):
    self.a = 43

thirdpartymodule_a.SomeClass.__init__ = new_init

thirdpartymodule_b.dosomething()

如果您希望新的 init 调用旧的 init,请将 new_init() 定义替换为以下内容:

If you want the new init to call the old init replace the new_init() definition with the following:

old_init = thirdpartymodule_a.SomeClass.__init__
def new_init(self, *k, **kw):
    old_init(self, *k, **kw)
    self.a = 43

这篇关于猴子在 Python 中的另一个模块中修补类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆