example - ¿Cuáles son las buenas reglas generales para las importaciones de Python?
python import from parent directory (10)
Estoy un poco confundido por la multitud de formas en que puedes importar módulos en Python.
import X
import X as Y
from A import B
He estado leyendo sobre el alcance y los espacios de nombres, pero me gustaría obtener algunos consejos prácticos sobre cuál es la mejor estrategia, en qué circunstancias y por qué. ¿Deberían ocurrir las importaciones a nivel de módulo o a nivel de método / función? ¿En __init__.py
o en el código del módulo en sí?
Mi pregunta no está respondida realmente por " paquetes de Python: importe por clase, no por archivo ", aunque obviamente está relacionado.
Alguien arriba dijo eso
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
es equivalente a
import X
import X
permite modificaciones directas a AP, mientras que from X import ...
crea copias de AP. Para from X import A..P
, no se actualizan las variables si se modifican. Si los modifica, solo modificará su copia, pero X sí sabe sobre sus modificaciones.
Si AP son funciones, no sabrá la diferencia.
Cuando tienes una biblioteca bien escrita, que a veces es un caso en python, solo debes importarla y usarla como tal. La biblioteca bien escrita tiende a quitar vida e idioma, resultando en un agradable código de lectura, donde raramente hace referencia a la biblioteca. Cuando una biblioteca está bien escrita, no debería necesitar cambiar el nombre ni demasiada frecuencia.
import gat
node = gat.Node()
child = node.children()
A veces no es posible escribirlo de esta manera, o bien, puede levantar cosas de la biblioteca que importó.
from gat import Node, SubNode
node = Node()
child = SubNode(node)
A veces haces esto por muchas cosas, si tu cadena de importación desborda 80 columnas, es una buena idea hacer esto:
from gat import (
Node, SubNode, TopNode, SuperNode, CoolNode,
PowerNode, UpNode
)
La mejor estrategia es mantener todas estas importaciones en la parte superior del archivo. Preferiblemente ordenados alfabéticamente, import-statements primero, luego de import-statements.
Ahora te digo por qué esta es la mejor convención.
Python podría haber tenido una importación automática, que se vería desde las principales importaciones para el valor cuando no se puede encontrar desde el espacio de nombres global. Pero esta no es una buena idea. Explico brevemente por qué. Además de ser más complicado de implementar que de simple importación, los programadores no pensarían tanto en las dependencias y descubrirían que las cosas importadas deberían hacerse de otra manera que solo investigar las importaciones.
La necesidad de descubrir las dependencias es una de las razones por las cuales las personas odian "de ... importar *". Sin embargo, existen algunos ejemplos malos donde necesita hacer esto, por ejemplo, opengl -wrappings.
Entonces, las definiciones de importación son realmente valiosas ya que definen las dependencias del programa. Es la forma en que deberías explotarlos. De ellos puede comprobar rápidamente de dónde se importa una función extraña.
En el código de producción de nuestra empresa, tratamos de seguir las siguientes reglas.
Colocamos las importaciones al principio del archivo, justo después del docstring del archivo principal, por ejemplo:
"""
Registry related functionality.
"""
import wx
# ...
Ahora, si importamos una clase que es una de las pocas en el módulo importado, importamos el nombre directamente, de modo que en el código solo tenemos que usar la última parte, por ejemplo:
from RegistryController import RegistryController
from ui.windows.lists import ListCtrl, DynamicListCtrl
Sin embargo, hay módulos que contienen docenas de clases, por ejemplo, una lista de todas las excepciones posibles. Luego importamos el módulo y hacemos referencia a él en el código:
from main.core import Exceptions
# ...
raise Exceptions.FileNotFound()
Usamos la import X as Y
más rara posible, porque dificulta la búsqueda del uso de un módulo o clase en particular. A veces, sin embargo, tiene que usarlo si desea importar dos clases que tienen el mismo nombre, pero existen en diferentes módulos, por ejemplo:
from Queue import Queue
from main.core.MessageQueue import Queue as MessageQueue
Como regla general, no hacemos importaciones dentro de los métodos; simplemente hacen que el código sea más lento y menos legible. Algunos pueden encontrar que esta es una buena manera de resolver fácilmente el problema de las importaciones cíclicas, pero una mejor solución es la reorganización del código.
Estoy con Jason en el hecho de no usar
from X import *
Pero en mi caso (no soy un programador experto, así que mi código no cumple con el estilo de codificación demasiado bien) suelo hacer en mis programas un archivo con todas las constantes como la versión del programa, autores, mensajes de error y todo eso, entonces el archivo son solo definiciones, luego hago la importación
from const import *
Eso me ahorra mucho tiempo. Pero es el único archivo que tiene esa importación, y es porque todo dentro de ese archivo son solo declaraciones variables.
Hacer ese tipo de importación en un archivo con clases y definiciones puede ser útil, pero cuando tiene que leer ese código, pasa mucho tiempo buscando funciones y clases.
La import X as Y
es útil si tiene implementaciones diferentes del mismo módulo / clase.
Con algunos try..import..except ImportError..import
anidados ... try..import..except ImportError..import
s, puede ocultar la implementación de su código. Ver ejemplo de importación lxml etree :
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")
NO hagas esto:
from X import *
a menos que esté absolutamente seguro de que usará todas y cada una de las cosas en ese módulo. E incluso entonces, probablemente debería reconsiderar el uso de un enfoque diferente.
Aparte de eso, es solo una cuestión de estilo.
from X import Y
es bueno y te ahorra mucho tipeo. Tiendo a usar eso cuando estoy usando algo con bastante frecuencia. Pero si está importando mucho de ese módulo, puede terminar con una declaración de importación que se ve así:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
Entiendes la idea. Ahí es cuando las importaciones como
import X
ser útil O eso o si realmente no estoy usando nada en X con mucha frecuencia.
Normalmente usaría import X
en el nivel del módulo. Si solo necesita un solo objeto de un módulo, use from X import Y
Solo use import X as Y
en caso de que se enfrente a un conflicto de nombres.
Solo uso importaciones en el nivel de función para importar cosas que necesito cuando el módulo se utiliza como el módulo principal, como:
def main():
import sys
if len(sys.argv) > 1:
pass
HTH
Otros han cubierto la mayor parte del terreno aquí, pero solo quería agregar un caso en el que usaré la import X as Y
(temporalmente), cuando estoy probando una nueva versión de una clase o módulo.
Entonces, si estábamos migrando a una nueva implementación de un módulo, pero no queríamos cortar la base de código sobre todos al mismo tiempo, podríamos escribir un módulo xyz_new
y hacer esto en los archivos fuente que habíamos migrado:
import xyz_new as xyz
Luego, una vez que cortemos toda la base de código, simplemente reemplazaríamos el módulo xyz
por xyz_new
y cambiaremos todas las importaciones nuevamente a
import xyz
Permítanme pegar una parte de la conversación en la lista de correo django-dev iniciada por Guido van Rossum:
[...] Por ejemplo, es parte de las guías de estilo de Google Python [1] que todas las importaciones deben importar un módulo, no una clase o función de ese módulo. Hay muchas más clases y funciones que módulos, por lo que recordar de dónde viene una cosa en particular es mucho más fácil si está prefijado con un nombre de módulo. A menudo, varios módulos definen cosas con el mismo nombre, por lo que un lector del código no tiene que volver a la parte superior del archivo para ver desde qué módulo se importa un nombre de pila.
Fuente: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
Por lo general, trato de usar el nombre de módulo de import modulename
regular, a menos que el nombre del módulo sea largo o se use con frecuencia.
Por ejemplo, yo haría ...
from BeautifulSoup import BeautifulStoneSoup as BSS
..so puedo hacer soup = BSS(html)
lugar de BeautifulSoup.BeautifulStoneSoup(html)
O..
from xmpp import XmppClientBase
..en lugar de importar todo el xmpp cuando solo uso XmppClientBase
Usar import x as y
es útil si quieres importar nombres de métodos muy largos, o para evitar una importación / variable / clase / método existente (algo que debes evitar por completo, pero no siempre es posible)
Digamos que quiero ejecutar una función main () desde otro script, pero ya tengo una función main ().
from my_other_module import main as other_module_main
..no reemplazaría mi función main
con el main
de my_other_module
Ah, una cosa, no lo hagas from x import *
, hace que tu código sea muy difícil de entender, ya que no puedes ver fácilmente de dónde vino un método ( from x import *; from y import *; my_func()
- where is mi_func definido?)
En todos los casos, puede import modulename
y luego hacer modulename.subthing1.subthing2.method("test")
...
El material from x import y as z
es puramente práctico: úselo cada vez que haga que su código sea más fácil de leer o escribir.