¿La statement de importación de Python también importa dependencias automáticamente?

Tengo el siguiente archivo app.py

 class Baz(): def __init__(self, num): self.a = num print self.a def foo(num): obj = Baz(num) 

y el segundo archivo main.py

 from app import foo foo(10) 

Ejecutando el archivo python main.py da la salida correcta.

Ahora en el segundo archivo, solo estoy importando la función, no la clase, aunque la ejecución exitosa de mi función también requiere la clase.

Al importar la función, ¿Python importa automáticamente todo lo demás que se necesita para ejecutar esa función, o busca automáticamente la clase en el directorio actual?

Como @DavidZ ya mencionó, todo el archivo de Python se comstack cuando lo importamos. Pero otra cosa especial sucede cuando se analiza el cuerpo de una función, una función sabe qué variables debe buscar en el scope local y qué variables debe buscar en el scope global (también hay variables libres).

 >>> import dis >>> dis.dis(foo) 7 0 LOAD_GLOBAL 0 (Baz) 3 LOAD_FAST 0 (num) 6 CALL_FUNCTION 1 9 STORE_FAST 1 (obj) 12 LOAD_CONST 0 (None) 15 RETURN_VALUE 

Entonces, aquí Baz debe ser recuperado del scope global.

Pero, ¿cómo identificar este scope global cuando importamos app.py en otro archivo?

Bueno, cada función tiene un atributo especial __globals__ adjunto que contiene su espacio de nombres global real. Por lo tanto, esa es la fuente de Baz :

 >>> foo.__globals__['Baz']  

Entonces, el diccionario de módulos de la aplicación y foo.__globals__ apuntan al mismo objeto:

 >>>sys.modules['app'].__dict__ is foo.__globals__ True 

Debido a esto, incluso si define otra variable llamada Baz en main.py después de importar foo , seguirá accediendo al Baz real.

Desde la página del modelo de datos :

__globals__ func_globals :

Una referencia al diccionario que contiene las variables globales de la función, el espacio de nombres global del módulo en el que se definió la función .

Python no hace automáticamente ninguna de estas cosas.

Cuando importa algo desde un módulo (en este caso, el módulo de la app ), Python ejecuta primero todo el código en el archivo correspondiente ( app.py ). El código en el archivo app.py que has escrito hace dos cosas:

  1. define la clase Baz
  2. define la función foo

Cuando se ejecuta la función foo , Python busca a Baz en el módulo del que foo forma parte, y solo allí. (Bueno, también verifica las variables locales definidas en la función foo , pero no tiene ninguna de ellas excepto obj .) Específicamente, busca app.Baz . Si modifica su main.py para hacer la misma búsqueda:

 from app import foo foo(10) import app # same app that was already imported print app.Baz 

verá que app.Baz es la clase que definió en app.py

Si pones la definición de la clase Baz en otro archivo, y si no importas ese archivo, Python no lo ejecutará. Esto muestra que Python no importa dependencias automáticamente. En particular, supongamos que app.py contiene

 def foo(num): obj = Baz(num) 

y baz.py contiene

 class Baz(): def __init__(self, num): self.a = num print self.a 

y main.py ha cambiado. Obtendrá un error porque Python no ha ejecutado el código para definir la clase Baz .