Importación de módulos en Python – mejores prácticas

Soy nuevo en Python, ya que quiero expandir las habilidades que aprendí usando R. En RI, tienden a cargar un montón de bibliotecas, lo que a veces genera conflictos de nombres de funciones.

¿Qué es la mejor práctica en Python. He visto algunas variaciones específicas que no veo una diferencia entre

import pandas , from pandas import * , y from pandas import DataFrame

¿Cuáles son las diferencias entre los dos primeros y debo importar lo que necesito? Además, ¿cuáles serían las peores consecuencias para alguien que hace pequeños progtwigs para procesar datos y calcular estadísticas simples?

ACTUALIZAR

He encontrado esta excelente guía . Eso lo explica todo.

import pandas importa el módulo de pandas bajo el espacio de nombres de pandas, por lo que deberá llamar a los objetos dentro de pandas usando pandas.foo .

from pandas import * importa todos los objetos del módulo de pandas a su espacio de nombres actual, por lo que debería llamar a objetos dentro de pandas usando solo foo . Tenga en cuenta que esto podría tener consecuencias injustificadas si hay algún conflicto de nombres entre su espacio de nombres actual y el espacio de nombres de los pandas.

from pandas import DataFrame es el mismo que el anterior, pero solo importa DataFrame (en lugar de todo) en su espacio de nombres actual.

En mi opinión, la primera es generalmente la mejor práctica, ya que mantiene los diferentes módulos bien compartimentados en su código.

Desventaja de cada forma.

Al leer el código de otras personas (y esas personas utilizan estilos de importación muy diferentes), noté los siguientes problemas con cada uno de los estilos:

import modulewithaverylongname el código con el nombre largo del módulo (por ejemplo, concurrent.futures o django.contrib.auth.backends ) y disminuirá la legibilidad en esos lugares.

from module import * no me da la oportunidad de ver de manera sintáctica que, por ejemplo, classA y classB provienen del mismo módulo y tienen mucho que ver entre sí. Hace que leer el código sea difícil . (Que los nombres de una importación de este tipo puedan hacer que los nombres de una importación anterior sean la parte menos importante de ese problema.)

from module import classA, classB, functionC, constantD, functionE sobrecarga mi memoria a corto plazo con demasiados nombres que mentalmente necesito asignar al module para entender el código de manera coherente.

import modulewithaverylongname as mwvln veces no es lo suficientemente mnemotécnico para .

Un compromiso adecuado.

Basándome en las observaciones anteriores, he desarrollado el siguiente estilo en mi propio código:

import module es el estilo preferido si el nombre del módulo es corto como, por ejemplo, la mayoría de los paquetes en la biblioteca estándar. También es el estilo preferido si necesito usar nombres del módulo en solo dos o tres lugares en mi propio módulo; La claridad triunfa sobre la brevedad ( “Cuenta de legibilidad” ).

import longername as ln es el estilo preferido en casi todos los demás casos. Por ejemplo, podría import django.contrib.auth.backends as dj_abe . Por la definición del criterio 1 anterior, la abreviatura se usará con frecuencia y, por lo tanto, es lo suficientemente fácil de memorizar.

Solo estos dos estilos son totalmente pythonic según “Explicit es mejor que implícito”. regla.

from module import xx todavía ocurre a veces en mi código. Lo uso en casos en los que incluso el formato as parece exagerado, el ejemplo más famoso es el from datetime import datetime .

En general es mejor hacer importaciones explícitas. Como en:

 import pandas frame = pandas.DataFrame() 

O:

 from pandas import DataFrame frame = DataFrame() 

Otra opción en Python, cuando tienes nombres en conflicto, es importar x como y:

 from pandas import DataFrame as PDataFrame from bears import DataFrame as BDataFrame frame1 = PDataFrame() frame2 = BDataFrame() 

Aquí hay algunas recomendaciones de la guía de estilo PEP8.

  1. Las importaciones deben estar generalmente en líneas separadas , por ejemplo:

     Yes: import os import sys No: import sys, os 

    pero está bien

     from subprocess import Popen, PIPE 
  2. Las importaciones siempre se colocan en la parte superior del archivo, justo después de los comentarios y las cadenas de documentación del módulo, y antes de las globales y constantes del módulo.

    • Las importaciones deben agruparse en el siguiente orden:
      1. biblioteca estándar de importaciones
      2. importaciones de terceros relacionadas
      3. Importaciones específicas de aplicaciones / bibliotecas locales
    • Debe poner una línea en blanco entre cada grupo de importaciones.
  3. Se recomiendan importaciones absolutas.
    Son más legibles y facilitan la depuración al dar mejores mensajes de error en caso de que arruine el sistema de importación.

     import mypkg.sibling from mypkg import sibling from mypkg.sibling import example 

    o importaciones relativas explícitas

     from . import sibling from .sibling import example 
  4. Las importaciones relativas implícitas nunca deben usarse y se eliminan en Python 3.

     No: from ..grand_parent_package import uncle_package 
  5. Deben evitarse las importaciones con comodines ( from import * ) , ya que no dejan claro qué nombres están presentes en el espacio de nombres, lo que confunde tanto a los lectores como a muchas herramientas automatizadas.


Algunas recomendaciones acerca de las lazy imports de los consejos de rendimiento de velocidad de Python

Declaración de importación de gastos generales

Las declaraciones de importación se pueden ejecutar en cualquier lugar. A menudo es útil colocarlas dentro de las funciones para restringir su visibilidad y / o reducir el tiempo de inicio inicial. Aunque el intérprete de Python está optimizado para no importar el mismo módulo varias veces, la ejecución repetida de una statement de importación puede afectar seriamente el rendimiento en algunas circunstancias.

El siguiente es un escenario explicado en la página,

 >>> def doit1(): ... import string ... string.lower('Python') ... >>> import string >>> def doit2(): ... string.lower('Python') ... >>> import timeit >>> t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()') >>> t.timeit() 11.479144930839539 >>> t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()') >>> t.timeit() 4.6661689281463623 
 from A import B 

esencialmente es igual a tres siguientes declaraciones

 import A B = AB del A 

Eso es todo, eso es todo.

Todos son adecuados en diferentes contextos (por lo que están disponibles todos). No hay un principio rector profundo, aparte de las declaraciones de maternidad genéricas sobre la claridad, la facilidad de mantenimiento y la simplicidad. Algunos ejemplos de mi propio código:

  1. import sys, os, re, itertools evita colisiones de nombres y proporciona una manera muy breve de importar un montón de módulos estándar.
  2. from math import * me permite escribir sin(x) lugar de math.sin(x) en código pesado en matemáticas. Esto se vuelve un poco arriesgado cuando también importo números, lo que se duplica en algunos de estos, pero no me preocupa demasiado, ya que en general son las mismas funciones. Además, tiendo a seguir la documentación numpy ( import numpy as np , que evita el problema por completo.
  3. Estoy a favor from PIL import Image, ImageDraw solo porque esa es la forma en que la documentación de PIL presenta sus ejemplos.