当前位置: 代码迷 >> python >> Python 中猴子补丁的底层是什么
  详细解决方案

Python 中猴子补丁的底层是什么

热度:89   发布时间:2023-06-16 13:58:15.0

我有点困惑并试图理解下面的内容,希望我能更好地理解 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导入模块的方式吗?

目标是拦截和修改您想要影响其行为的函数将使用的引用。 最初, a.SomeClassb.SomeClass指向同一个对象; 但补丁将用其他内容替换这些引用之一。

在文档中,示例是您要修改some_function看到和使用的SomeClass 所以重要的是some_function()如何引用SomeClass

  1. 如果some_function包含为纯的参考SomeClass :,它将被解析为它自己的模块中的变量b在本实施例中(顺带b通过导入它创建了这个变量)。 因此b.SomeClass是需要修补的。

  2. 如果some_function显式引用a.SomeClass ,那么这就是需要修补的引用。

假设模块b.py包含以下行:

import a
from a import SomeClass

应该修补哪个参考? 为什么, some_function使用的那个! 重要的不是它如何导入b ,而是使用它的代码如何访问它。

这一切都与命名空间有关。

b.py内部,当from a import SomeClass的命令执行时, SomeClass被添加到模块b命名空间中。 因此,您有b.SomeClass

在其他情况下,当仍然里面b.py和执行该命令import a ,所发生的一切是模块b现在可以访问模块的名称空间a 所以从全局的角度来看,在b内部使用的类仍然是a.SomeClass

  相关解决方案