问题描述
我有点困惑并试图理解下面的内容,希望我能更好地理解 Monkey Patch。
我已经阅读了,我知道我必须从你使用模块的地方打补丁。 但是在文档中。
a.py
-> Defines SomeClass
b.py
-> from a import SomeClass
-> some_function instantiates SomeClass
如果我from a import SomeClass执行此操作
然后我必须像这样打补丁。
@patch('b.SomeClass')
但是,为什么我像这样导入模块。
import a
相反,我必须像这样使用补丁。
@patch('a.SomeClass')
我只知道如何使用补丁,但我不明白为什么会这样? 这是Python导入模块的方式吗?
1楼
目标是拦截和修改您想要影响其行为的函数将使用的引用。
最初, a.SomeClass和b.SomeClass指向同一个对象;
但补丁将用其他内容替换这些引用之一。
在文档中,示例是您要修改some_function看到和使用的SomeClass 。
所以重要的是some_function()如何引用SomeClass :
如果
some_function包含为纯的参考SomeClass:,它将被解析为它自己的模块中的变量b在本实施例中(顺带b通过导入它创建了这个变量)。 因此b.SomeClass是需要修补的。如果
some_function显式引用a.SomeClass,那么这就是需要修补的引用。
假设模块b.py包含以下两行:
import a
from a import SomeClass
应该修补哪个参考?
为什么, some_function使用的那个!
重要的不是它如何导入b ,而是使用它的代码如何访问它。
2楼
这一切都与命名空间有关。
在b.py内部,当from a import SomeClass的命令执行时, SomeClass被添加到模块b的命名空间中。
因此,您有b.SomeClass 。
在其他情况下,当仍然里面b.py和执行该命令import a ,所发生的一切是模块b现在可以访问模块的名称空间a 。
所以从全局的角度来看,在b内部使用的类仍然是a.SomeClass 。