2015-02-21 2 views
0

Когда оболочка import модуль один, я думал, что один будет импортировать два и запустить код два так будет импортировать три автоматически. Таким образом, три названия модулей будут включены в список dir().пространство имен циркулярной импорта

Фактически, когда я проверяю пространство имен, только модуль один (см. Ниже).

Как можно напечатать 'Hello' без включения в пространство имен модуля два и три? Поскольку one.f1() полагается на оба модуля.

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

'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() 

ответ

4

Каждый модуль имеет свой собственный пространство имен, в том числе основного сценария. Вы импортировали только модуль one в пространство имен основного скрипта.

Другие модули импортируются в пространства имен для модуля one и модуля two, соответственно.

Фактически, импорт только на самом деле означает, что вы создали ссылку на импортированные элементы (здесь объекты модуля) в текущем пространстве имен. Python будет убедиться, что модуль загружен первым (это когда вы видите выполняемые операторы print()), после чего происходит фактический импорт (привязка имен в текущем пространстве имен).

Таким образом, утверждение import one делает две вещи:

  • Найти и загрузить модуль one, раз, если он еще не был загружен. Это включает в себя создание модуля и вставку имен в него.
  • Связать имя one в текущем пространстве имен с модулем.

Модули хранятся в sys.modules; они хранятся там, когда начинается загрузка.

В вашем случае загрузка модуля one вызывает другой импорт, поэтому Python загружает модуль two для удовлетворения этого импорта. Это, в свою очередь, вызывает импорт модуля three. three импорт one, модуль уже присутствует в sys.modules. Таким образом, имя one не представляет проблемы, так как есть модуль для привязки уже. Этот модуль по-прежнему пуст (поскольку он все еще находится в процессе загрузки).

Полная последовательность событий:

  • import one -> Нет такой модуль в sys.modules
    • Создать sys.modules['one'], код загрузки и начать выполнение
    • import two -> Нет такой модуль в sys.modules
    • Создать sys.modules['two'], код загрузки и начать выполнение
    • import three -> Нет такой модуль в sys.modules
      • Создать sys.modules['three'], код загрузки и начать выполнение
      • import one ->sys.modules['one'] существует, связать one с sys.modules['one'].
      • print('in three')
      • Создать функцию f3.
      • Загрузка завершена для three
    • Bind three к sys.modules['three']
    • print ('In two')
    • Создать функцию f2
    • Загрузка завершена для two
    • Bind two к sys.modules['two']
    • print('in one')
    • Создание функций f1 и f4
    • Загрузка завершена для one
  • Execute one.f1()
    • one.f1() существует и выполняется ->two.f2()
    • two.f2() существует и выполняется ->three.f3()
      • three.f3() существует и выполняется ->one.f4()
      • one.f4() существует и выполняется>print('Hello')

Тот факт, что one.f4() не сделал еще существует, когда three.f3() была создана здесь не имеет значения ; имя запускается только при выполнении функции.

+0

Спасибо! Вы полностью решили мой вопрос. –

Смежные вопросы