The key to understanding what happens is to realize that in your __init__.py
,
from bar import a
in effect does something like
a = bar.a # … as if bar were imported
and defines a new variable (bar/__init__.py:a
, if you wish).
Thus, when you do
import bar
print bar.a
you are accessing the copy bar/__init__.py:a
(since import bar
imports your bar/__init__.py
). And when you subsequently do
bar.foobar()
you call bar/bar.py:foobar()
, which accesses the original bar/bar.py:a
, which is None
. Hence the last None
output.
Thus, your from bar import a
in __init__.py
creates a new copy named a
of the original bar.py:a
. This is why you can do from bar import a as copy_a
in __init__.py
: in this case, you have bar/bar.py:a
and a distinct copy bar/__init__.py:copy_a
.