La primera vez que import goo
desde cualquier lugar (dentro o fuera de una función), goo.py
(u otra forma importable) se carga y sys.modules['goo']
se establece en el objeto de módulo así construido. Cualquier importación futura dentro de la misma ejecución del programa (de nuevo, ya sea dentro o fuera de una función) simplemente busque sys.modules['goo']
y conéctelo a barename goo
en el alcance apropiado. La búsqueda Dict y el enlace de nombre son operaciones muy rápidas.
Suponiendo que el primer import
consigue totalmente amortizados en ejecución del programa de todas formas, tener el "ámbito correspondiente" módulo de nivel significa que cada uso de goo.this
, goo.that
, etc, es decir dos búsquedas dict - uno para goo
y otro para el nombre del atributo. Tenerlo como "nivel de función" paga una configuración de variable local adicional por ejecución de la función (¡incluso más rápido que la parte de búsqueda del diccionario!) Pero guarda una búsqueda dict (intercambiándola por una búsqueda de variable local, increíblemente rápida) para cada goo.this
(etc.) acceden, básicamente, a la mitad del tiempo que tardan esas búsquedas.
Estamos hablando de unos nanosegundos de una forma u otra, por lo que no es una optimización que valga la pena. La ventaja potencialmente sustancial de tener el import
dentro de una función es cuando esa función puede no ser necesaria en absoluto en una ejecución determinada del programa, por ejemplo, esa función se ocupa de errores, anomalías y situaciones raras en general; si ese es el caso, cualquier ejecución que no necesite la funcionalidad ni siquiera realizará la importación (y eso es un ahorro de microsegundos, no solo nanosegundos), solo las ejecuciones que necesiten la funcionalidad pagarán el precio (modesto pero mensurable).
Todavía es una optimización que solo vale la pena en situaciones bastante extremas, y hay muchas otras que consideraría antes de tratar de exprimir microsegundos de esta manera.
No hay ningún beneficio de velocidad (llamar 'import' es muy caro, incluso si el módulo ya está cargado). Si desea un beneficio de velocidad, es más rápido (si accede al módulo al menos 4-5 veces) simplemente asignar el módulo a una variable local como lo primero que hace en su función, y luego acceder a través de esa variable local (porque las búsquedas de variables locales son MUY rápidas). –
(Avance rápido hasta las 26:30 en el video en http://us.pycon.org/2010/conference/schedule/event/71/ si desea un ejemplo interesante de cuán ridículamente mala puede ser la importación en una función) –
@Nick: al escuchar esto, parece que es lento importarlo repetidamente, ya que cada vez que lo intenta, comprueba si se importó o no. ¿Estás diciendo que, fuera de la función, la importa y la configura como una variable global y capta la variable global dentro de la función? –