导入模块的Python作用域和名称空间

时间:2018-07-31 18:27:54

标签: python scope namespaces

我对如何在Python中确定范围和名称空间感到困惑。假设我的文件系统如下:

|-test1.py
 -test2.py

每个文件的定义如下:

test1.py:

#!/usr/bin/python
def test1():
    print('test1')

test2.py:

#!/usr/bin/python
from test1 import test1
def test2():
    test1()
    print('test2')

在python交互式解释器中,如果执行以下操作:

import test2
test2.test2()

,代码可以正常运行并给出以下结果:

test1
test2

从输出中,我们可以看到解释器可以正确识别test1()函数对象。在执行过程中导入test1.test1时,我感到困惑的是?该对象何时进入全球范围?

基于@Ziyad Edher的答案,我创建了一个维恩图来说明不同作用域之间的关系。假设解释器被第三个文件test3.py代替。它们的范围如下:圆圈代表范围,File test3test3.pyFile test2test2.pytest2()指功能{ test2()中的{1}},test2.pytest1()中的功能test1()test1.py的范围没有test2(),因此解释器将引用上级范围test1()。范围File test2具有File test2,并对其进行调用。

enter image description here

1 个答案:

答案 0 :(得分:1)

Python模块导入和全局名称空间管理是一个非常广泛的主题,因此,我将把这个答案限于您所看到的特定情况。

通常,Python的工作顺序非常顺畅。

  1. 打开解释器,某些特殊值(例如环境变量和其他内核变量)将注入到全局名称空间中。
  2. 您执行import test2,这将转到本地目录中的test2.py文件,并在相同的Python环境中执行该文件。
  3. 在执行test2.py时,Python遇到了from test1 import test1
  4. 类似于步骤2,Python继续查找test1.py,它做了一些额外的事情,因为您是在模块中而不是模块本身中导入一个函数,但是通常来说,{{1} }(该函数)被置于当前作用域中。
  5. 您致电test1,因为test2.test2()已在步骤2中导入,所以它存在,test2也是如此。因此,解释器跳至test2.test2并被调用test2.test2,由于它在名称空间中(我们在步骤3中刚刚导入了它),没有抛出错误,因此调用了第二个print语句。

在底层,事情显然比这要复杂一些,但这确实提供了Python如何处理这些东西的一般概述。