Se recomienda no usar import *
en Python.
¿Alguien puede compartir la razón de eso, para evitar que lo haga la próxima vez?
python
python-import
Software entusiasta
fuente
fuente
import *
no funciona para mí en primer lugar en Python 2 o 3.Respuestas:
Debido a que pone muchas cosas en su espacio de nombres (podría ocultar algún otro objeto de la importación anterior y no lo sabrá).
Porque no sabe exactamente qué se importa y no puede encontrar fácilmente desde qué módulo se importó una determinada cosa (legibilidad).
Porque no puedes usar herramientas geniales como
pyflakes
detectar estáticamente errores en tu código.fuente
numpy.any
sombreadoany
cuando lo hacenfrom numpy import *
o una herramienta "útil" lo hace por ellos.import *
hace que el orden de lasimport
declaraciones sea significativo ... incluso para los módulos de biblioteca estándar que normalmente no se preocupan por el orden de importación . Algo tan inocente como alfabetizar susimport
declaraciones podría romper su guión cuando una víctima anterior de la guerra de importación se convierte en el único sobreviviente. (Incluso si su script funciona ahora y nunca cambia, podría fallar repentinamente algún tiempo después si el módulo importado introduce un nuevo nombre que reemplaza al que confiaba).De acuerdo con el Zen de Python :
... no se puede discutir con eso, ¿verdad?
fuente
use strict
(JavaScriptvar
). Por otro lado, por supuesto, Python no es sin tipo (de hecho, está fuertemente tipado). De todos modos, incluso si tuviera razón, esto todavía contradiría el Zen de Python, citado en esta respuesta.No pasas
**locals()
a las funciones, ¿verdad?Dado que Python carece de una declaración de "inclusión", y el
self
parámetro es explícito, y las reglas de alcance son bastante simples, generalmente es muy fácil señalar con el dedo una variable y decir de dónde proviene ese objeto, sin leer otros módulos y sin ningún tipo de IDE (que están limitadas en la forma de introspección de todos modos, por el hecho de que el lenguaje es muy dinámico).El
import *
rompe todo eso.Además, tiene una posibilidad concreta de ocultar errores.
Ahora, si el módulo de barra tiene alguno de los atributos "
os
", "mystuff
", etc., anulará los importados explícitamente y posiblemente apuntará a cosas muy diferentes. La definición__all__
en la barra a menudo es sabia, esto indica lo que se importará implícitamente, pero aún así es difícil rastrear de dónde provienen los objetos, sin leer y analizar el módulo de barra y seguir sus importaciones. Una red deimport *
es lo primero que soluciono cuando tomo posesión de un proyecto.No me malinterpreten: si
import *
faltaran, lloraría por tenerlo. Pero tiene que ser usado con cuidado. Un buen caso de uso es proporcionar una interfaz de fachada sobre otro módulo. Del mismo modo, el uso de declaraciones de importación condicionales, o importaciones dentro de espacios de nombres de función / clase, requiere un poco de disciplina.Creo que en proyectos medianos a grandes, o pequeños con varios contribuyentes, se necesita un mínimo de higiene en términos de análisis estático, ejecutando al menos pyflakes o incluso mejor un pylint configurado correctamente, para detectar varios tipos de errores antes Ellos pasan.
Por supuesto, dado que esto es python, siéntase libre de romper las reglas y explorar, pero tenga cuidado con los proyectos que podrían multiplicarse por diez, si el código fuente no tiene disciplina, será un problema.
fuente
execfile()
. Afortunadamente, rara vez se usa y desaparece en 3.x.**vars()
incluimos globales si la función llamada está en otro archivo? : PEstá bien hacerlo
from ... import *
en una sesión interactiva.fuente
doctest
cuerda? ¿Seimport *
interpreta dentro de una "caja de arena" en este caso? Gracias.Eso es porque estás contaminando el espacio de nombres. Importará todas las funciones y clases en su propio espacio de nombres, lo que puede chocar con las funciones que usted mismo defina.
Además, creo que usar un nombre calificado es más claro para la tarea de mantenimiento; puede ver en la línea de código de dónde proviene una función, por lo que puede consultar los documentos con mucha más facilidad.
En el módulo foo:
En su código:
fuente
http://docs.python.org/tutorial/modules.html
fuente
Digamos que tiene el siguiente código en un módulo llamado foo:
y luego en tu propio módulo tienes:
Ahora tiene un módulo difícil de depurar que parece que tiene etree de lxml, pero realmente tiene ElementTree en su lugar.
fuente
Estas son todas buenas respuestas. Voy a agregar que cuando enseño a nuevas personas a codificar en Python, lidiar con esto
import *
es muy difícil. Incluso si usted o ellos no escribieron el código, sigue siendo un obstáculo.Enseño a niños (alrededor de 8 años) a programar en Python para manipular Minecraft. Me gusta darles un entorno de codificación útil para trabajar ( Atom Editor ) y enseñarles el desarrollo impulsado por REPL (a través de bpython ). En Atom, encuentro que las sugerencias / finalización funcionan tan efectivamente como bpython. Afortunadamente, a diferencia de otras herramientas de análisis estadístico, Atom no se deja engañar
import *
.Sin embargo, tomemos este ejemplo ... En este contenedor , hay
from local_module import *
un montón de módulos que incluyen esta lista de bloques . Ignoremos el riesgo de colisiones en el espacio de nombres. Al hacerlofrom mcpi.block import *
, hacen que esta lista completa de tipos oscuros de bloques sea algo que debe mirar para saber qué hay disponible. Si en su lugar lo hubieran usadofrom mcpi import block
, podría escribirwalls = block.
y luego aparecería una lista de autocompletar.fuente
Entendido los puntos válidos que la gente pone aquí. Sin embargo, tengo un argumento que, a veces, "importar estrellas" no siempre es una mala práctica:
const.py
:import const
, entonces, para cada constante, tengo que referirme a estoconst.SOMETHING
, lo que probablemente no sea la forma más conveniente.from const import SOMETHING_A, SOMETHING_B ...
, entonces obviamente es demasiado detallado y frustra el propósito de la estructuración.from const import *
puede ser una mejor opción.fuente
Es una práctica muy MALA por dos razones:
Para el punto 1 : Veamos un ejemplo de esto:
Aquí, al ver el código, nadie tendrá idea de qué módulo
b
,c
y end
realidad pertenece.Por otro lado, si lo haces así:
Es mucho más limpio para usted, y también la nueva persona que se una a su equipo tendrá una mejor idea.
Para el punto 2 : Digamos ambos
module1
ymodule2
tengamos una variable comob
. Cuando lo hago:Aquí
module1
se pierde el valor de . Será difícil depurar por qué el código no funciona, incluso sib
está declaradomodule1
y he escrito el código esperando que mi código usemodule1.b
Si tiene las mismas variables en diferentes módulos y no desea importar el módulo completo, incluso puede hacer lo siguiente:
fuente
Como prueba, creé un módulo test.py con 2 funciones A y B, que imprimen respectivamente "A 1" y "B 1". Después de importar test.py con:
. . . Puedo ejecutar las 2 funciones como test.A () y test.B (), y "test" aparece como un módulo en el espacio de nombres, así que si edito test.py, puedo volver a cargarlo con:
Pero si hago lo siguiente:
no hay referencia a "prueba" en el espacio de nombres, por lo que no hay forma de volver a cargarlo después de una edición (por lo que puedo decir), lo cual es un problema en una sesión interactiva. Considerando que cualquiera de los siguientes:
agregará "prueba" o "tt" (respectivamente) como nombres de módulo en el espacio de nombres, lo que permitirá volver a cargar.
Si lo hago:
los nombres "A" y "B" aparecen en el espacio de nombres como funciones . Si edito test.py y repito el comando anterior, las versiones modificadas de las funciones no se vuelven a cargar.
Y el siguiente comando genera un mensaje de error.
Si alguien sabe cómo volver a cargar un módulo cargado con "from module import *", publique. De lo contrario, esta sería otra razón para evitar el formulario:
fuente
Como se sugiere en los documentos, (casi) nunca debe usar
import *
en el código de producción.Si bien la importación
*
desde un módulo es mala, la importación * desde un paquete es aún peor. De manera predeterminada,from package import *
importa los nombres definidos por el paquete__init__.py
, incluidos los submódulos del paquete que se cargaron enimport
declaraciones anteriores .Sin embargo, si el
__init__.py
código de un paquete define una lista llamada__all__
, se considera que es la lista de nombres de submódulos que deben importarse cuandofrom package import *
se encuentra.Considere este ejemplo (suponiendo que no haya
__all__
definido ensound/effects/__init__.py
):La última instrucción importará los módulos
echo
ysurround
en el espacio de nombres actual (posiblemente anulando las definiciones anteriores) porque se definen en elsound.effects
paquete cuandoimport
se ejecuta la instrucción.fuente