python - name - ¿Es pitónico importar funciones internas?
python package name (7)
PEP 8 dice:
- Las importaciones siempre se colocan en la parte superior del archivo, justo después de los comentarios de los módulos y las cadenas de documentos, y antes de los módulos globales y constantes.
En occation, violo PEP 8. Algunas veces importo cosas dentro de funciones. Como regla general, hago esto si hay una importación que solo se usa dentro de una sola función.
Alguna opinion?
EDITAR (la razón por la que creo que importar en funciones puede ser una buena idea):
Motivo principal: puede hacer que el código sea más claro.
- Al mirar el código de una función, me podría preguntar: "¿Qué es la función / clase xxx?" (xxx se usa dentro de la función). Si tengo todas mis importaciones en la parte superior del módulo, tengo que buscar allí para determinar qué es xxx. Esto es más un problema cuando se usa
from m import xxx
. Verm.xxx
en la función probablemente me diga más. Dependiendo de quém
es: ¿Es un módulo / paquete de nivel superior bien conocido (import m
)? ¿O es un submódulo / paquete (from abc import m
)? - En algunos casos, tener esa información adicional ("¿Qué es xxx?") Cerca de donde se usa xxx puede facilitar la comprensión de la función.
A la larga, creo que apreciarás tener la mayoría de tus importaciones en la parte superior del archivo, de esa manera puedes ver de un vistazo qué tan complicado es tu módulo por lo que necesita importar.
Si agrego un nuevo código a un archivo existente, normalmente haré la importación donde sea necesario y, si el código se mantiene, haré las cosas más permanentes moviendo la línea de importación hasta la parte superior del archivo.
Otro punto, prefiero obtener una excepción ImportError antes de ejecutar cualquier código, como una verificación de cordura, por lo que esa es otra razón para importar en la parte superior.
Yo uso pyChecker para buscar módulos no utilizados.
Aquí están los cuatro casos de uso de importación que usamos
import
(yfrom x import y
eimport x as y
) en la parte superiorOpciones para importar En la cima.
import settings if setting.something: import this as foo else: import that as foo
Importación condicional. Usado con JSON, bibliotecas XML y similares. En la cima.
try: import this as foo except ImportError: import that as foo
Importación dinámica. Hasta ahora, solo tenemos un ejemplo de esto.
import settings module_stuff = {} module= __import__( settings.some_module, module_stuff ) x = module_stuff[''x'']
Tenga en cuenta que esta importación dinámica no trae código, sino que incorpora estructuras de datos complejas escritas en Python. Es como una pieza de datos en escabeche, excepto que lo decapamos a mano.
Esto también es, más o menos, en la parte superior de un módulo
Esto es lo que hacemos para que el código sea más claro:
Mantenga los módulos cortos.
Si tengo todas mis importaciones en la parte superior del módulo, tengo que buscar allí para determinar qué nombre es. Si el módulo es corto, es fácil de hacer.
En algunos casos, tener esa información adicional cerca de donde se usa un nombre puede hacer que la función sea más fácil de entender. Si el módulo es corto, es fácil de hacer.
En dos ocasiones violo PEP 8 en este sentido:
- Importaciones circulares: el módulo A importa el módulo B, pero algo en el módulo B necesita el módulo A (aunque esto a menudo es una señal de que necesito refactorizar los módulos para eliminar la dependencia circular)
- Insertar un punto de corte pdb:
import pdb; pdb.set_trace()
import pdb; pdb.set_trace()
Esto es práctico b / c. No quiero poner laimport pdb
en la parte superior de cada módulo que me gustaría depurar, y es fácil recordar eliminar la importación cuando elimino el punto de interrupción.
Fuera de estos dos casos, es una buena idea poner todo en la parte superior. Hace las dependencias más claras.
Rompí esta regla antes para los módulos que se autoevalúan. Es decir, normalmente solo se utilizan como soporte, pero defino una principal para ellos, de modo que si los ejecuta por sí solo puede probar su funcionalidad. En ese caso, a veces importo getopt
y cmd
solo en main, porque quiero que quede claro para alguien que lee el código que estos módulos no tienen nada que ver con el funcionamiento normal del módulo y solo se incluyen para la prueba.
Siempre y cuando sea import
y no from x import *
, debe ponerlo en la parte superior. Agrega solo un nombre al espacio de nombre global, y se apega a PEP 8. Además, si luego lo necesita en otro lugar, no tiene que mover nada.
No es gran cosa, pero como casi no hay diferencia, te sugiero que hagas lo que dice PEP 8.
Una cosa a tener en cuenta: las importaciones innecesarias pueden causar problemas de rendimiento. Entonces, si esta es una función que se llamará con frecuencia, será mejor que coloque la importación en la parte superior. Por supuesto, esto es una optimización, por lo que si hay un caso válido que hacer la importación dentro de una función es más clara que la importación en la parte superior de un archivo, que supera el rendimiento en la mayoría de los casos.
Si estás haciendo IronPython, me dicen que es mejor importar funciones internas (ya que compilar código en IronPython puede ser lento). Por lo tanto, puede obtener una forma de importar funciones internas. Pero aparte de eso, diría que simplemente no vale la pena luchar contra la convención.
Como regla general, hago esto si hay una importación que solo se usa dentro de una sola función.
Otro punto que me gustaría hacer es que este puede ser un problema potencial de mantenimiento. ¿Qué ocurre si agrega una función que utiliza un módulo que anteriormente solo era utilizado por una función? ¿Te acordarás de agregar la importación al principio del archivo? ¿O va a escanear todas y cada una de las funciones para las importaciones?
FWIW, hay casos en los que tiene sentido importar dentro de una función. Por ejemplo, si desea establecer el idioma en cx_Oracle, debe establecer una variable de entorno NLS _
LANG antes de importarla. Por lo tanto, puede ver un código como este:
import os
oracle = None
def InitializeOracle(lang):
global oracle
os.environ[''NLS_LANG''] = lang
import cx_Oracle
oracle = cx_Oracle
Viniendo de la pregunta sobre cargar el módulo dos veces , ¿por qué no las dos?
Una importación en la parte superior de la secuencia de comandos indicará las dependencias y otra importación en la función para hacer que esta función sea más atómica, mientras que aparentemente no causa ninguna desventaja de rendimiento, ya que una importación consecutiva es barata.