Один из источников трудностей в этом вопросе состоит в том, что у вас есть программа с именем bar/bar.py
: import bar
, которая импортирует либо bar/__init__.py
, либо bar/bar.py
, в зависимости от того, где она выполняется, что делает ее немного громоздкой для отслеживания того, какиеa
is bar.a
.
Вот как это работает:
Ключ к пониманию того, что происходит, заключается в осознании того, что в вашем __init__.py
,
from bar import a
в действительности делает что-то вроде
a = bar.a # … with bar = bar/bar.py (as if bar were imported locally from __init__.py)
и определяет новую переменную (bar/__init__.py:a
, если хотите).Таким образом, ваш from bar import a
в __init__.py
связывает имя bar/__init__.py:a
с исходным bar.py:a
объектом (None
).Вот почему вы можете сделать from bar import a as a2
в __init__.py
: в этом случае ясно, что у вас есть как bar/bar.py:a
, так и отличное имя переменной bar/__init__.py:a2
(в вашем случае именадве переменные просто имеют значение a
, но они все еще живут в разных пространствах имен: в __init__.py
они bar.a
и a
).
Теперь, когда вы делаете
import bar
print bar.a
вы обращаетесь к переменной bar/__init__.py:a
(поскольку import bar
импортирует bar/__init__.py
).Это переменная, которую вы изменяете (до 1).Вы не касаетесь содержимого переменной bar/bar.py:a
.Поэтому, когда вы впоследствии делаете
bar.foobar()
, вы вызываете bar/bar.py:foobar()
, который обращается к переменной a
из bar/bar.py
, которая по-прежнему None
(когда определено foobar()
, оно связывает имена переменных один рази для всех, таким образом, a
в bar.py
- это bar.py:a
, а не любая другая переменная a
, определенная в другом модуле (поскольку во всех импортируемых модулях может быть много переменных a
).Отсюда последний None
вывод.