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

jar*_*ied 2 python class dynamic

我要加载class dynamically.

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

B
Run Code Online (Sandbox Code Playgroud)

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

MainClass.property is None! 
Run Code Online (Sandbox Code Playgroud)

MainClass.py的代码如下:

from MyClassA import MyClassA, main

if __name__ == '__main__':
    MyClassA.property = 'B'
    main()
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

MyClassB.py的代码如下:

from MyClassA import MyClassA


class MyClassB(MyClassA):
    pass
Run Code Online (Sandbox Code Playgroud)

a_g*_*est 5

这是因为MyClassA导入的对象与调用该脚本作为主脚本MyClassB.py不同。原因是 Python 将为导入创建一个新的模块对象(与module不同)。您可以通过在类定义后添加来验证这一点,这将输出以下内容:MyClassA.py:MyClassA__main__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'>]
Run Code Online (Sandbox Code Playgroud)

现在,由于您进行了定义class MainClass(module_class_object, MyClassA),因此出现在MROmodule_class_object中的较早位置。即,当您询问时,会找到该属性,而不是您修改的类。MainClass.property<class 'MyClassA.MyClassA'><class '__main__.MyClassA'>

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