Une source de difficulté à cette question est que vous avez un programme nommé bar/bar.py: les import barimportations soit bar/__init__.pyou bar/bar.py, selon l'endroit où il est fait, ce qui le rend un peu lourd à suivre ce qui aest bar.a.
Voici comment cela fonctionne:
La clé pour comprendre ce qui se passe est de réaliser que dans votre __init__.py,
from bar import a
en effet fait quelque chose comme
a = bar.a
# … where bar = bar/bar.py (as if bar were imported locally from __init__.py)
et définit une nouvelle variable ( bar/__init__.py:asi vous le souhaitez). Ainsi, votre from bar import ain __init__.pylie le nom bar/__init__.py:aà l' bar.py:aobjet d' origine ( None). C'est pourquoi vous pouvez le faire from bar import a as a2dans __init__.py: dans ce cas, il est clair que vous avez les deux bar/bar.py:aet un nom de variable distinctbar/__init__.py:a2 (dans votre cas, les noms des deux variables se trouvent être les deux a, mais ils vivent toujours dans des espaces de noms différents: dans __init__.py, ils sont bar.aet a).
Maintenant, quand tu fais
import bar
print bar.a
vous accédez à la variable bar/__init__.py:a(depuis import barimporte votre bar/__init__.py). C'est la variable que vous modifiez (à 1). Vous ne touchez pas au contenu de la variable bar/bar.py:a. Alors quand tu fais par la suite
bar.foobar()
vous appelez bar/bar.py:foobar(), qui accède à la variable à apartir de bar/bar.py, qui est toujours None(quand foobar()est défini, il lie les noms de variable une fois pour toutes, donc le ain bar.pyn'est bar.py:apas une autre avariable définie dans un autre module - car il peut y avoir de nombreuses avariables dans tous les modules importés ). D'où la dernière Nonesortie.
Conclusion: il est préférable d'éviter toute ambiguïté import bar, par n'avoir aucun module (depuis répertoire marques un paquet déjà, que vous pouvez également importer avec ).bar/bar.pybar.__init__.pybar/import bar