Yog*_*gaj 5 python import python-import
以下两个陈述有何不同,每个陈述的后果是什么?
导入为:
from module.submodule import someclass as myclass
Run Code Online (Sandbox Code Playgroud)
赋值给一个变量:
from module.submodule import someclass
myclass = someclass
Run Code Online (Sandbox Code Playgroud)
此处给出的字节码输出适用于 Python 3.4,但生成字节码的代码应该适用于任何版本,并且适用相同的一般原则。
马具:
from dis import dis
def compile_and_dis(src):
dis(compile(src, '<string>', 'exec'))
Run Code Online (Sandbox Code Playgroud)
情况1:
>>> 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
Run Code Online (Sandbox Code Playgroud)
这是唯一一种仅将一个名称 ( myclass) 添加到当前名称中的方法locals()(即__dict__,它将成为globals()模块中定义的所有内容)。它也是最短的字节码。
ImportError如果someclass在 中找不到,此方法将引发module.submodule。但是,它将尝试module.submodule.someclass作为模块加载。
案例2:
>>> 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
Run Code Online (Sandbox Code Playgroud)
这与情况 1 几乎相同,只是它将第二个名称 ( someclass) 泄漏到本地名称空间中。如果导入和分配不连续,理论上您确实会冒着将该名称重复用于其他用途的风险,但如果您要隐藏名称,那么无论如何您的设计都会很糟糕。
请注意字节码中无用的STORE_NAME/循环(围绕不相关的)。LOAD_NAMEPOP_TOP
案例3:
>>> 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
Run Code Online (Sandbox Code Playgroud)
这种方法会泄漏submodule到本地命名空间中。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
Run Code Online (Sandbox Code Playgroud)
这与情况 3 类似,但要求它module.submodule是一个模块。
案例5:
>>> 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
Run Code Online (Sandbox Code Playgroud)
此方法类似于情况 4,尽管 2 个属性加载位于不同的位置,因此不同的变量泄漏到本地命名空间中。
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |