Python 在同一模块中为类的使用的函数打monkey补丁
问题描述
我想修改一个模块中的函数(而不是方法),以便使用该函数的同一模块中的类表现得不同。
为了简单起见,假设我有一个名为_module.py
的文件和一个名为__init__.py
的文件,它们放置在名为my_library
的目录中。
# file _module.py
def _do_something():
print('hello')
class foo():
def bar(self):
_do_something()
# file __init__.py
from ._module import foo
我已经尝试了对函数 _do_something
进行猴子补丁,就像这样:
import my_library
my_library._do_something = lambda: print('goodbye')
a = my_library.foo()
a.bar()
但它仍然输出
hello
我还尝试了以下方式
from my_library import foo, _do_something
_do_something = lambda: print('goodbye')
a = foo()
a.bar()
但是它抛出了一个错误:cannot import name '_do_something' from 'my_library'
。
我该如何修改_do_something
,以便在调用foo.bar
时反映出更改?
附言:实际上,我想修改sklearn.mixture.GaussianMixture
使用的_estimate_gaussian_parameters
函数,而且两者都在同一个文件中。但我认为这与问题无关。
解决方案
你应该修补_module
中的函数,而不是my_library
中导入的那个:
import my_library
my_library._module._do_something = lambda: print('goodbye')
a = my_library.foo()
a.bar()
此外,我建议使用unittest.mock
(有关patch的文档,请参阅文档):
import my_library
from unittest.mock import patch
with patch.object(my_library._module, '_do_something', lambda: print('goodbye')):
a = my_library.foo()
a.bar()