Una fuente de dificultad con esta pregunta es que usted tiene un programa llamado bar/bar.py
: import bar
importaciones ya sea bar/__init__.py
o bar/bar.py
, dependiendo de dónde se hace, que se convierte en un poco engorroso para realizar un seguimiento de lo que es a
bar.a
.
Así es como funciona:
La clave para entender lo que ocurre es darse cuenta de que en su __init__.py
,
from bar import a
en efecto tiene algo así como
a = bar.a # … with bar = bar/bar.py (as if bar were imported locally from __init__.py)
y define una nueva variable (bar/__init__.py:a
, si lo desea). Por lo tanto, su from bar import a
en __init__.py
se une a la nombre bar/__init__.py:a
bar.py:a
objeto original (None
). Es por esto que se puede hacer from bar import a as a2
en __init__.py
: en este caso, está claro que usted tiene tanto bar/bar.py:a
y una distinta nombre de la variable bar/__init__.py:a2
(en su caso, los nombres de las dos variables que pasa es que tanto sea a
, pero todavía viven en diferentes espacios de nombres: en __init__.py
, son bar.a
y a
).
Ahora, cuando lo hace
import bar
print bar.a
que está accediendo a variables bar/__init__.py:a
(ya import bar
Las importaciones de su bar/__init__.py
). Esta es la variable que modifica (a 1). No está tocando el contenido de la variable bar/bar.py:a
. Así que cuando posteriormente se hace
bar.foobar()
se llama bar/bar.py:foobar()
, que accede a la variable a
de bar/bar.py
, que sigue siendo None
(cuando se define foobar()
, que une los nombres de variables de una vez por todas, por lo que el a
en bar.py
es bar.py:a
, no a
cualquier otra variable definida en otro módulo, ya que puede haber muchos a
variables en todos los módulos importados). De ahí la última salida None
.
En realidad, encuentro el P La forma de 'importación' de ython es mucho más limpia que la de Java, ya que los espacios de nombres/ámbitos siempre se deben mantener separados adecuadamente y nunca interferir entre sí de manera inesperada. Como aquí: Alterar un enlace de un objeto a un nombre en un espacio de nombres (leer: asignar algo a la propiedad global de un módulo) nunca afecta a otros espacios de nombres (leer: la referencia que se importó) en Python. Pero lo hace en Java, etc. En Python solo necesita comprender lo que se importa, mientras que en Java, también debe comprender el otro módulo en caso de que modifique este valor importado más adelante. – Tino
Tengo que estar en desacuerdo bastante enérgicamente. La importación/inclusión/uso tiene un largo historial de uso del formulario de referencia y no del valor en casi todos los demás idiomas. –
Maldita sea, presiono regresar ... hay una expectativa de importación por referencia (según @OP). De hecho, un nuevo programador de Python, sin importar cuán experimentado sea, tiene que ser dicho de esta manera "a la vista". Eso nunca debería suceder: basado en el uso común, Python tomó el camino equivocado. Cree un "valor de importación" si es necesario, pero no combine los símbolos con los valores en el momento de la importación. –