【问题标题】:Why do I get different results when calling from different file locations?为什么从不同的文件位置调用时会得到不同的结果?
【发布时间】:2021-11-26 16:57:48
【问题描述】:

我要加载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

【问题讨论】:

    标签: python class dynamic


    【解决方案1】:

    这是因为MyClassB.py 中导入的MyClassA 对象与MyClassA.py:MyClassA 在调用该脚本作为主脚本不同。原因是 Python 将为导入创建一个 new 模块对象(与 __main__ module 不同)。您可以通过在类定义后添加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 时,它会在&lt;class 'MyClassA.MyClassA'&gt; 中找到该属性,而不是您修改的类&lt;class '__main__.MyClassA'&gt;

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

    【讨论】:

    • 即使在运行“MyClassA.py”时,有没有办法得到“B”的结果?后来我尝试了'import importlib',但似乎没有得到我想要的结果。
    • @jaried 在不了解大局的情况下,很难提出合适的解决方案。也许您可以提供一些额外的信息,为什么您需要 MainClass 的这种动态导入和定义?似乎一种直接的方法是将main 函数和MyClassA 分离到两个不同的模块中,并将MyClassA 导入到定义main 的模块中。
    • 感谢您的建议。在我将main() 函数从MyClassA 移动到MainClass 之后,这就是我想要的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    相关资源
    最近更新 更多