问题描述
我有点困惑并试图理解下面的内容,希望我能更好地理解 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
。