Mejores prácticas de importación de Python (y Django)

De las diversas formas de importar código, ¿hay algunas formas que sean preferibles de usar en comparación con otras? Este enlace http://effbot.org/zone/import-confusion.htm en breve indica que

from foo.bar import MyClass 

no es la forma preferida de importar MyClass en circunstancias normales o a menos que sepa lo que está haciendo. (Más bien, una mejor manera le gustaría:

 import foo.bar as foobaralias 

y luego en el código, para acceder al uso de MyClass.

 foobaralias.MyClass 

)

En resumen, parece que el enlace al que se hace referencia arriba dice que generalmente es mejor importar todo desde un módulo, en lugar de solo partes del módulo.

Sin embargo, ese artículo que he enlazado es realmente viejo.

También escuché que es mejor, al menos en el contexto de los proyectos de Django, importar solo las clases que desea usar, en lugar de todo el módulo. Se ha dicho que esta forma ayuda a evitar errores de importación circular o al menos hace que el sistema de importación django sea menos frágil. Se señaló que el propio código de Django parece preferir “de x import y” a “import x”.

Suponiendo que el proyecto en el que estoy trabajando no use ninguna característica especial de __init__.py … (todos nuestros archivos __init__.py están vacíos), ¿qué método de importación debo favorecer y por qué?

Para mí, depende de la situación. Si es un método / clase con nombre único (es decir, no process() o algo así), y lo va a usar mucho , luego guarde la escritura y solo hágalo from foo import MyClass .

Si está importando varias cosas de un módulo, probablemente sea mejor que solo importe el módulo, y haga lo module.bar, module.foo, module.baz , module.bar, module.foo, module.baz , etc., para mantener limpio el espacio de nombres.

Tu tambien dijiste

Se ha dicho que esta forma ayuda a evitar errores de importación circular o al menos hace que el sistema de importación django sea menos frágil. Se señaló que el propio código de Django parece preferir “de x import y” a “import x”.

No veo cómo una u otra forma ayudaría a prevenir las importaciones circulares. La razón es que incluso cuando se hace from x import y , se importa TODO de x . Solo y se introduce en el espacio de nombres actual, pero se procesa todo el módulo x . Prueba este ejemplo:

En test.py, pon lo siguiente:

 def a(): print "a" print "hi" def b(): print "b" print "bye" 

Luego en ‘runme.py’, pon:

 from test import b b() 

Entonces haz python runme.py

Verás la siguiente salida:

 hi bye b 

Así que se ejecutó todo en test.py, aunque solo importó b

Primera y principal regla de importación: nunca utilice from foo import * .

El artículo está discutiendo el tema de las importaciones cíclicas, que todavía existe hoy en día en un código mal estructurado. No me gustan las importaciones cíclicas; su presencia es una señal clara de que algún módulo está haciendo demasiado y debe dividirse. Si por alguna razón necesita trabajar con código con importaciones cíclicas que no se pueden reorganizar, la única opción es import foo .

Para la mayoría de los casos, no hay mucha diferencia entre import foo y from foo import MyClass . Prefiero la segunda, porque hay menos escritura, pero hay algunas razones por las que podría usar la primera:

  • El módulo y la clase / valor tienen nombres diferentes. Puede ser difícil para los lectores recordar de dónde proviene una importación en particular, cuando el nombre del valor importado no está relacionado con el módulo.

    • Bueno: import myapp.utils as utils; utils.frobnicate() import myapp.utils as utils; utils.frobnicate()
    • Bueno: import myapp.utils as U; U.frobnicate() import myapp.utils as U; U.frobnicate()
    • Malo: from myapp.utils import frobnicate
  • Estás importando muchos valores de un módulo. Guarda tus dedos, y los ojos del lector.

    • Malo: from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada

La ventaja de este último es que el origen de MyClass es más explícito. El primero coloca a MyClass en el espacio de nombres actual para que el código solo pueda usar MyClass sin calificar. Entonces, es menos obvio para alguien que lee el código donde se define MyClass.