猴子在 Python 中的另一个模块中修补类 [英] Monkey patching a class in another module in 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
我在上面的例子中忽略了一个很小但很重要的细节.SomeClass
由 thirdpartymodule_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屋!