为什么从不同的文件位置调用时会得到不同的结果?

Why do I get different results when calling from different file locations?

我要加载classdynamically.

我有三个文件,MainClass.pyMyClassA.pyMyClassB.py。为什么我从 MainClass.pyMyClassA.py 运行 different results? 当从MainClass.py宁运行时,结果是:

B

这是我想要的结果。 当从 MyClassA.py 宁 运行 时,结果是:

MainClass.property is None! 

MainClass.py的代码如下:

from MyClassA import MyClassA, main

if __name__ == '__main__':
    MyClassA.property = 'B'
    main()

MyClassA.py的代码如下:

import importlib


class MyClassA:
    property = None


def main():
    module_name = 'MyClass' + MyClassA.property
    class_name = module_name
    module_object = importlib.import_module(module_name)
    module_class_object = getattr(module_object, class_name)

    '''
    The reason why I quote MyClassA here is that because module_class_object is dynamically loaded,
    PyCharm cannot automatically prompt related content when writing code,
    and the upper class is subject to the first one,
    so I put MyClassA in the second referenced for my convenience PyCharm writes code.
    '''
    
    class MainClass(module_class_object, MyClassA):
        pass

    if MainClass.property is None:
        print('MainClass.property is None!')
    else:
        print(MainClass.property)


if __name__ == '__main__':
    MyClassA.property = 'B'
    main()

MyClassB.py的代码如下:

from MyClassA import MyClassA


class MyClassB(MyClassA):
    pass

这是因为在 MyClassB.py 中导入的 MyClassA 对象与 MyClassA.py:MyClassA 不同 调用该脚本作为 主脚本。原因是 Python 将为导入创建一个 new 模块对象(与 __main__ module 不同)。您可以通过在 class 定义后添加 print(MainClass.mro()) 来验证,这将输出以下内容:

# python MainClass.py
[<class 'MyClassA.main.<locals>.MainClass'>,
 <class 'MyClassB.MyClassB'>,
 <class 'MyClassA.MyClassA'>,
 <class 'object'>]

# python MyClassA.py
[<class '__main__.main.<locals>.MainClass'>,
 <class 'MyClassB.MyClassB'>,
 <class 'MyClassA.MyClassA'>,
 <class '__main__.MyClassA'>,
 <class 'object'>]

现在因为您定义了 class MainClass(module_class_object, MyClassA),所以 module_class_object 出现在 MRO 的前面。 IE。当您请求 MainClass.property 时,它会在 <class 'MyClassA.MyClassA'> 中找到该属性,而不是 <class '__main__.MyClassA'>,这是您修改的 class。

另一方面,当 运行 python MainClass.py 时,两个模块(__main__MyClassB.py)导入 相同的 模块对象 MyClassA 因为它缓存在 sys.modules 中。因此,对该模块中定义的对象所做的所有更改都将在使用模块 MyClassA.

的所有其他模块之间共享。