为什么从不同的文件位置调用时会得到不同的结果?
Why do I get different results when calling from different file locations?
我要加载class
dynamically
.
我有三个文件,MainClass.py
、MyClassA.py
和 MyClassB.py
。为什么我从 MainClass.py
和 MyClassA.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
.
的所有其他模块之间共享。
我要加载class
dynamically
.
我有三个文件,MainClass.py
、MyClassA.py
和 MyClassB.py
。为什么我从 MainClass.py
和 MyClassA.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
.