gpt4 book ai didi

'import as' 与变量赋值之间的 Python 区别

转载 作者:太空狗 更新时间:2023-10-30 02:19:11 26 4
gpt4 key购买 nike

以下两种说法有何不同,每种说法的后果是什么?

导入为:

from module.submodule import someclass as myclass

赋值给一个变量:

from module.submodule import someclass
myclass = someclass

最佳答案

此处给出的字节码输出适用于 Python 3.4,但生成字节码的代码应该适用于任何版本,并且适用相同的一般原则。

线束:

from dis import dis

def compile_and_dis(src):
dis(compile(src, '<string>', 'exec'))

案例一:

>>> compile_and_dis('from module.submodule import someclass as myclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('someclass',))
6 IMPORT_NAME 0 (module.submodule)
9 IMPORT_FROM 1 (someclass)
12 STORE_NAME 2 (myclass)
15 POP_TOP
16 LOAD_CONST 2 (None)
19 RETURN_VALUE

这是唯一一种只将一个名称(myclass)添加到当前 locals()(即 __dict__)的方法,它将成为globals() 用于模块中定义的所有内容)。也是最短的字节码。

如果在 module.submodule 中找不到 someclass,此方法将引发 ImportError。但是,它将尝试将 module.submodule.someclass 作为模块加载。

案例二:

>>> compile_and_dis('from module.submodule import someclass; myclass = someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('someclass',))
6 IMPORT_NAME 0 (module.submodule)
9 IMPORT_FROM 1 (someclass)
12 STORE_NAME 1 (someclass)
15 POP_TOP
16 LOAD_NAME 1 (someclass)
19 STORE_NAME 2 (myclass)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE

这与情况 1 几乎相同,只是它向本地命名空间泄漏了第二个名称 (someclass)。如果导入和分配不连续,理论上您确实会冒着将名称重用于其他内容的风险,但如果您隐藏名称,那么您的设计无论如何都会很糟糕。

注意字节码中无用的 STORE_NAME/LOAD_NAME 循环(围绕不相关的 POP_TOP)。

案例三:

>>> compile_and_dis('from module import submodule; myclass = submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('submodule',))
6 IMPORT_NAME 0 (module)
9 IMPORT_FROM 1 (submodule)
12 STORE_NAME 1 (submodule)
15 POP_TOP
16 LOAD_NAME 1 (submodule)
19 LOAD_ATTR 2 (someclass)
22 STORE_NAME 3 (myclass)
25 LOAD_CONST 2 (None)
28 RETURN_VALUE

这种方法将 submodule 泄漏到本地 namespace 中。如果找不到该类,它不会引发 ImportError,而是在分配期间引发 AttributeError。它不会尝试将 module.submodule.someclass 作为模块加载(事实上什至不关心 module.submodule 是否是模块)。

案例 4:

>>> compile_and_dis('import module.submodule as submodule; myclass = submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (module.submodule)
9 LOAD_ATTR 1 (submodule)
12 STORE_NAME 1 (submodule)
15 LOAD_NAME 1 (submodule)
18 LOAD_ATTR 2 (someclass)
21 STORE_NAME 3 (myclass)
24 LOAD_CONST 1 (None)
27 RETURN_VALUE

这与情况 3 类似,但要求 module.submodule 是一个模块。

案例五:

>>> compile_and_dis('import module.submodule; myclass = module.submodule.someclass')
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (module.submodule)
9 STORE_NAME 1 (module)
12 LOAD_NAME 1 (module)
15 LOAD_ATTR 2 (submodule)
18 LOAD_ATTR 3 (someclass)
21 STORE_NAME 4 (myclass)
24 LOAD_CONST 1 (None)
27 RETURN_VALUE

此方法类似于案例 4,尽管 2 个属性加载位于不同的位置,因此不同的变量会泄漏到本地命名空间中。

关于 'import as' 与变量赋值之间的 Python 区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31716388/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com