Python 循环导入的命名空间

Python 循环导入的命名空间,python,python-3.x,import,namespaces,Python,Python 3.x,Import,Namespaces,当shellimport模块one时,我认为one将导入two,并运行two的代码,因此它将自动导入two。因此,模块的三个名称都将包含在dir()中 实际上,当我检查名称空间时,只有模块一个(见下文) 它如何打印'Hello',而不包括模块two和two的名称空间?因为one.f1()依赖于两个模块 >>> ================================ RESTART ================================ >>>

当shell
import
模块one时,我认为one将导入two,并运行two的代码,因此它将自动导入two。因此,模块的三个名称都将包含在
dir()

实际上,当我检查名称空间时,只有模块一个(见下文)

它如何打印
'Hello'
,而不包括模块twotwo的名称空间?因为
one.f1()
依赖于两个模块

>>> ================================ RESTART ================================
>>> import one
in three
In two
in one
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'one']
>>> one.f1()
Hello
>>> 



每个模块都有自己的名称空间,包括主脚本。您只将模块
one
导入到主脚本命名空间中

其他模块分别导入到模块
one
和模块
two
的名称空间中

事实上,导入实际上意味着您在当前名称空间中创建了对导入项(此处为模块对象)的引用。Python将确保首先加载模块(当您看到执行
print()
语句时),然后进行实际导入(当前名称空间中的名称绑定)

因此,语句
importone
执行两件事:

  • 如果模块尚未加载,则查找并加载模块一次。这包括创建模块并在其中插入名称
  • 将当前命名空间中的名称
    one
    绑定到模块
模块存储在
系统中。模块
;装载开始时,它们就存放在那里

在您的例子中,加载模块
one
会触发另一个导入,因此Python加载模块
two
以满足该导入。这反过来会触发模块
三的导入<代码>三个
导入
一个
,一个模块已经存在于
系统模块
中。因此名称
one
不存在问题,因为已经有一个模块要绑定。该模块仍然为空(因为它仍在加载过程中)

事件的完整顺序是:

  • 导入一个
    ->系统模块中没有此类模块
  • 创建
    sys.modules['one']
    ,加载代码并开始执行
  • 导入两个
    ->
    系统模块中没有这样的模块
  • 创建
    sys.modules['two']
    ,加载代码并开始执行
  • 导入三个
    ->
    系统模块中没有这样的模块
    • 创建
      sys.modules['three']
      ,加载代码并开始执行
    • import one
      ->
      sys.modules['one']
      存在,将
      one
      绑定到
      sys.modules['one']
    • print('in three')
    • 创建功能
      f3
    • 3的加载完成
  • three
    绑定到
    sys.modules['three']
  • print('In two')
  • 创建函数
    f2
  • 两个<代码>的加载完成
  • two
    绑定到
    sys.modules['two']
  • print('in one')
  • 创建函数
    f1
    f4
  • one的加载完成
  • 执行
    one.f1()
    • one.f1()
      存在并被执行->
      two.f2()
    • two.f2()
      存在并被执行->
      two.f3()
      • three.f3()
        已存在并已执行->
        one.f4()
      • one.f4()
        存在并被执行>
        print('Hello')
  • 创建
    three.f3()
    时,
    one.f4()
    还不存在,这一事实在这里并不重要;只有在执行函数时才会查找名称。

    每个模块都有自己的名称空间,包括主脚本。您只将模块
    one
    导入到主脚本命名空间中

    其他模块分别导入到模块
    one
    和模块
    two
    的名称空间中

    事实上,导入实际上意味着您在当前名称空间中创建了对导入项(此处为模块对象)的引用。Python将确保首先加载模块(当您看到执行
    print()
    语句时),然后进行实际导入(当前名称空间中的名称绑定)

    因此,语句
    importone
    执行两件事:

    • 如果模块尚未加载,则查找并加载模块一次。这包括创建模块并在其中插入名称
    • 将当前命名空间中的名称
      one
      绑定到模块
    模块存储在
    系统中。模块
    ;装载开始时,它们就存放在那里

    在您的例子中,加载模块
    one
    会触发另一个导入,因此Python加载模块
    two
    以满足该导入。这反过来会触发模块
    三的导入<代码>三个
    导入
    一个
    ,一个模块已经存在于
    系统模块
    中。因此名称
    one
    不存在问题,因为已经有一个模块要绑定。该模块仍然为空(因为它仍在加载过程中)

    事件的完整顺序是:

    • 导入一个
      ->系统模块中没有此类模块
    • 创建
      sys.modules['one']
      ,加载代码并开始执行
    • 导入两个
      ->
      系统模块中没有这样的模块
    • 创建
      sys.modules['two']
      ,加载代码并开始执行
    • 导入三个
      ->
      系统模块中没有这样的模块
      • 创建
        sys.modules['three']
        ,l
        'one.py'
        import two
        print('in one')
        
        def f1():
            two.f2()
        
        def f4():
            print ('Hello')
        
        'two.py'
        import three
        print ('In two')
        
        def f2():
            three.f3()
        
        'three.py'
        import one
        print('in three')
        def f3():
            one.f4()