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

查看:194
本文介绍了猴子在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 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.

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 by thirdpartymodule_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 than thirdpartymodule_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屋!

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