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

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

提问人:jaried 提问时间:10/6/2021 最后编辑:jaried 更新时间:10/6/2021 访问量:227

问:

我想加载 .classdynamically

我有三个文件,和 .我为什么要逃避 和 ? 当从 运行时,结果是:MainClass.pyMyClassA.pyMyClassB.pydifferent resultsMainClass.pyMyClassA.pyMainClass.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
Python 动态

评论


答:

5赞 a_guest 10/6/2021 #1

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

现在,因为您定义了 ,所以 出现在 MRO 的前面。也就是说,当你要求它时,它会找到那个属性,而不是你修改的类。class MainClass(module_class_object, MyClassA)module_class_objectMainClass.property<class 'MyClassA.MyClassA'><class '__main__.MyClassA'>

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

评论

0赞 jaried 10/6/2021
有没有办法即使在运行“MyClassA.py”时也能得到“B”的结果?我后来尝试“导入 importlib”,但它似乎没有得到我想要的结果。
0赞 a_guest 10/6/2021
@jaried 如果不了解大局,就很难提出适当的解决方案。也许您可以提供一些额外的信息,为什么需要这种动态导入和定义?似乎一种简单的方法是将函数分离到两个不同的模块中,然后导入到定义 .MainClassmainMyClassAMyClassAmain
0赞 jaried 10/6/2021
谢谢你的建议。将函数从 移动到 后,这就是我想要的结果。main()MyClassAMainClass