wpx usa shipment number international dhl delivery python python-import

python - usa - mt dhl



¿Por qué es "import*" malo? (11)

Como prueba, creé un módulo test.py con 2 funciones A y B, que respectivamente imprimen "A 1" y "B 1". Después de importar test.py con:

import test

. . . Puedo ejecutar las 2 funciones como test.A () y test.B (), y "prueba" aparece como un módulo en el espacio de nombres, así que si edito test.py puedo recargarlo con:

import importlib importlib.reload(test)

Pero si hago lo siguiente:

from test import *

no hay ninguna 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), que es un problema en una sesión interactiva. Considerando que cualquiera de los siguientes:

import test import test as tt

agregará "prueba" o "tt" (respectivamente) como nombres de módulo en el espacio de nombres, lo que permitirá volver a cargar.

Si lo hago:

from test import *

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 provoca un mensaje de error.

importlib.reload(test) # Error - name ''test'' is not defined

Si alguien sabe cómo volver a cargar un módulo cargado con "de la importación del módulo *", publique. De lo contrario, esta sería otra razón para evitar la forma:

from module import *

Se recomienda no usar import * en Python.

¿Alguien puede compartir la razón de eso, para poder evitarlo la próxima vez?


De acuerdo con el Zen de Python :

Explícito es mejor que implícito.

... no se puede discutir con eso, seguramente?


Entender los puntos válidos que las personas ponen aquí. Sin embargo, tengo un argumento de que, a veces, "importación de estrellas" no siempre es una mala práctica:

  • Cuando quiero estructurar mi código de tal manera que todas las constantes vayan a un módulo llamado const.py :
    • Si import const , entonces para cada constante, debo referirlo como const.SOMETHING , que probablemente no sea la forma más conveniente.
    • Si lo hago from const import SOMETHING_A, SOMETHING_B ... , obviamente es demasiado detallado y frustra el propósito de la estructuración.
    • Por lo tanto, creo que en este caso, hacer una from const import * puede ser una mejor opción.

Es una práctica MUY MALA por dos razones:

  1. Legibilidad del código
  2. Riesgo de anular las variables / funciones, etc.

Para el punto 1 : veamos un ejemplo de esto:

from module1 import * from module2 import * from module3 import * a = b + c - d

Aquí, al ver el código, nadie tendrá idea con respecto a qué módulo pertenecen realmente b , c y d .

Por otro lado, si lo haces como:

# v v will know that these are from module1 from module1 import b, c # way 1 import module2 # way 2 a = b + c - module2.d # ^ will know it is from module2

Es mucho más limpio para ti, y también la nueva persona que se una a tu equipo tendrá una mejor idea.

Para el punto 2 : supongamos que tanto el module1 como el module2 tienen una variable como b . Cuando lo hago:

from module1 import * from module2 import * print b # will print the value from module2

Aquí el valor del module1 se pierde. Será difícil depurar por qué el código no funciona, incluso si b se declara en el module1 y he escrito el código esperando que mi código use module1.b

Si tiene las mismas variables en diferentes módulos y no desea importar el módulo completo, puede hacer:

from module1 import b as mod1b from module2 import b as mod2b


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 entrar en conflicto con las funciones que defina usted mismo.

Además, creo que usar un nombre calificado es más claro para la tarea de mantenimiento; se ve en la línea de código de donde proviene una función, por lo que puede ver los documentos mucho más fácilmente.

En el módulo foo:

def myFunc(): print 1

En tu código:

from foo import * def doThis(): myFunc() # Which myFunc is called? def myFunc(): print 2


Está bien hacer from ... import * en una sesión interactiva.


Estas son todas buenas respuestas. Voy a agregar que cuando se enseña a las personas nuevas a codificar en Python, lidiar con la 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 (de aproximadamente 8 años) a programar en Python para manipular Minecraft. Me gusta darles un entorno de codificación útil para trabajar con ( Atom Editor ) y enseñar el desarrollo impulsado por REPL (a través de bpython ). En Atom encuentro que las sugerencias / finalización funcionan tan bien como bpython. Afortunadamente, a diferencia de otras herramientas de análisis estadístico, Atom no se deja engañar por la import * .

Sin embargo, tomemos este ejemplo ... En este envoltorio ellos from local_module import * un grupo de módulos que incluye esta lista de bloques . Vamos a ignorar el riesgo de colisiones de espacios de nombres. Al hacerlo from mcpi.block import * , hacen que toda esta lista de tipos de bloques oscuros sea algo que hay que consultar para saber qué hay disponible. Si, en cambio, hubieran usado el from mcpi import block , entonces podría escribir walls = block. y luego aparecería una lista de autocompletar.


Supongamos que tiene el siguiente código en un módulo llamado foo:

import ElementTree as etree

y luego en tu propio módulo tienes:

from lxml import etree from foo import *

Ahora tiene un módulo difícil de depurar que parece que tiene etree de lxml, pero en realidad tiene ElementTree.


Usted no pasa **locals() a funciones, ¿verdad?

Como Python carece de una declaración "include", y el parámetro self es explícito, y las reglas de scoping son bastante simples, por lo general es muy fácil señalar con un dedo una variable e indicar de dónde proviene ese objeto, sin leer otros módulos y sin ningún tipo de IDE (que están limitados en el modo de introspección de todos modos, por el hecho de que el lenguaje es muy dinámico).

La import * rompe todo eso.

Además, tiene una posibilidad concreta de ocultar errores.

import os, sys, foo, sqlalchemy, mystuff from bar import *

Ahora, si el módulo de barra tiene alguno de los atributos " os ", " mystuff ", etc ..., anulará los importados explícitamente y posiblemente señale cosas muy diferentes. Definir __all__ en la barra a menudo es sabio, esto indica lo que se importará implícitamente, pero aún así es difícil rastrear de dónde vienen los objetos, sin leer y analizar el módulo de la barra y seguir sus importaciones. Una red de import * es lo primero que soluciono cuando tomo posesión de un proyecto.

No me malinterpreten: si la import * faltaba, lloraría por tenerla. Pero debe usarse con cuidado. Un buen caso de uso es proporcionar una interfaz de fachada sobre otro módulo. Del mismo modo, el uso de sentencias de importación condicionales, o importaciones dentro de espacios de nombres de funciones / clases, 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 una píxel configurada correctamente, para detectar varios tipos de errores. Ellos pasan.

Por supuesto, dado que esto es Python, siéntete libre de romper reglas y explorar, pero desconfía de los proyectos que podrían multiplicarse por diez, si el código fuente no tiene disciplina, será un problema.



  • Porque pone muchas cosas en su espacio de nombres (puede sombrear algún otro objeto de la importación anterior y usted no lo sabrá).

  • Porque no sabe exactamente qué se importa y no puede encontrar fácilmente desde qué módulo se importó cierta cosa (legibilidad).

  • Debido a que no puede usar herramientas geniales como pyflakes para detectar errores de forma estática en su código.