猴子在Python的另一个模块中修补一个类 [英] Monkey patching a class in another module in Python
问题描述
我正在使用别人写的模块。我想猴子补丁模块中定义的类的 __ init __
方法。我发现显示如何做的例子都假设我自己调用类(例如猴子-patch Python class )。然而,情况并非如此。在我的情况下,类在另一个模块中的函数中初始化。请参阅下面的(大大简化的)示例:
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.dosomething()
以任何方式修改
SomeClass
的__ init __
方法,以便当dosomething
从mymodule.py调用,例如,打印43而不是42?理想情况下,我可以包装现有的方法。
我不能更改thirdpartymodule * .py文件,因为其他脚本依赖于现有的功能。我不想创建自己的模块副本,因为我需要做的更改非常简单。
编辑2013-10-24
在上面的例子中,我忽略了一个小但重要的细节。
由
thirdpartymodule_b
导入如下:从thirdpartymodule_a import SomeClass
。
要做FJ建议的补丁,我需要替换
thirdpartymodule_b
中的副本,而不是thirdpartymodule_a
。例如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()
定义:old_init = thirdpartymodule_a.SomeClass .__ init__
def new_init(self,* k,** kw):
old_init (self,* k,** kw)
self.a = 43
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.dosomething()
Is there any way to modify the
__init__
method ofSomeClass
so that whendosomething
is called from mymodule.py it, for example, prints 43 instead of 42? Ideally I'd be able to wrap the existing method.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.
Edit 2013-10-24
I overlooked a small but important detail in the example above.
SomeClass
is imported bythirdpartymodule_b
like this:from thirdpartymodule_a import SomeClass
.To do the patch suggested by F.J I need to replace the copy in
thirdpartymodule_b
, rather thanthirdpartymodule_a
. e.g.thirdpartymodule_b.SomeClass.__init__ = new_init
.解决方案The following should work:
import thirdpartymodule_a import thirdpartymodule_b def new_init(self): self.a = 43 thirdpartymodule_a.SomeClass.__init__ = new_init thirdpartymodule_b.dosomething()
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屋!