Siempre he estado usando este método:
from sys import argv
y use argv
con solo argv . Pero hay una convención de usar esto:
import sys
y usar argv por sys.argv
El segundo método hace que el código se auto-documente y yo (realmente) me adhiero a él. Pero la razón por la que prefiero el primer método es que es rápido porque estamos importando solo la función que se necesita en lugar de importar el módulo completo (que contiene más funciones inútiles que Python perderá el tiempo importándolas). Tenga en cuenta que solo necesito argv y todas las demás funciones de sys son inútiles para mí.
Así que mis preguntas lo son. ¿El primer método realmente hace que el script sea rápido? ¿Qué método es el más preferido? ¿Por qué?
Comentarios
Respuesta
Importar el módulo no desperdicia nada ; el módulo siempre está completo importado (en el mapeo sys.modules
), por lo que si usa import sys
o from sys import argv
no tiene probabilidades.
La única diferencia entre las dos declaraciones es qué nombre está vinculado; import sys
vincula el nombre sys
al módulo (por lo que sys
-> sys.modules["sys"]
), mientras que from sys import argv
enlaza un nombre diferente, argv
, apuntando directamente al atributo contenido dentro del módulo (entonces argv
-> sys.modules["sys"].argv
). El resto de th El módulo sys
todavía está allí, ya sea que use algo más del módulo o no.
Tampoco hay diferencia de rendimiento entre los dos enfoques. Sí, sys.argv
tiene que buscar dos cosas; tiene que buscar sys
en su espacio de nombres global (encuentra el módulo), luego buscar el atributo argv
. Y sí, al usar from sys import argv
puede omitir la búsqueda de atributos, ya que ya tiene una referencia directa al atributo. Pero la instrucción import
aún tiene que hacer ese trabajo, busca el mismo atributo al importar y usted «solo necesitará usar argv
una vez . Si tuviera que usar argv
miles de veces en un bucle, tal vez podría hacer una diferencia, pero en este caso específico realmente no .
La elección entre uno u otro debe basarse en el estilo de codificación .
En un módulo grande , Ciertamente usaría import sys
; La documentación del código es importante, y el uso de sys.argv
en algún lugar de un módulo grande hace que sea mucho más claro a qué te refieres de lo que solo argv
lo haría.
Si el único lugar en el que utiliza argv
es en un bloque "__main__"
para llamar a un main()
, use from sys import argv
si se siente más feliz con eso:
if __name__ == "__main__": from sys import argv main(argv)
I «Todavía usaría import sys
allí yo mismo. En igualdad de condiciones (y son, exactamente, en términos de rendimiento y número de caracteres utilizados para escribirlo) , eso es más agradable para mí.
Si está importando algo diferente por completo, entonces quizás el rendimiento entre en juego. Pero solo si usa un nombre específico en un módulo muchas veces , en un ciclo crítico, por ejemplo. Pero luego crear un nombre local (dentro de una función) será aún más rápido:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Comentarios
- También existe la situación en la que tiene un paquete con subpaquetes o módulos que expone un atributo de uno de esos subpaquetes / módulos en el paquete de nivel superior. El uso de
from...import
le permite hacerpackage.attribute
en lugar depackage.subpackage_or_module.attribute
, lo que puede ser útil si tienen agrupaciones lógicas o conceptuales dentro del paquete, pero quieren hacer las cosas un poco más convenientes para los usuarios de su paquete. (numpy
hace algo como esto, creo). - En django tienes toneladas de puntos donde cosas como
from django.core.management.base import BaseCommand
son mejores, y cualquier otra cosa (especialmenteimport django
) conduciría a un código ilegible. Entonces, aunque me gusta esta respuesta, creo que hay algunas bibliotecas (y especialmente algunos marcos) en las que la convención es violar la importación básica.Como siempre, utilice su criterio sobre lo que es mejor en una situación determinada. Pero errar por el lado de lo explícito (en otras palabras, estoy de acuerdo en su mayor parte). - @JAB: aún puede usar
import ... as
para encontrar el paquete un nombre diferente:import package.subpackage_or_module as shortname
.from parent import sub
hace, esencialmente, lo mismo. -
so wether you use import sys or from sys import argv makes no odds
este no parece ser el caso con IDLE. solo importar el módulo no importa sus funciones y puedo llamarlo en el shell IDLE solo por < module >. < función > nombre - @Suncatcher: lea mi respuesta completa. La oración que cita habla de cuánto se está importando, no de qué nombre está vinculado. Eso ‘ está cubierto en otra parte de la respuesta.
Respuesta
Hay dos razones a favor de usar import module
en lugar de from module import function
.
Primero está el espacio de nombres. Importar una función en el espacio de nombres global corre el riesgo de colisiones de nombres.
El segundo no es tan relevante para los módulos estándar, pero sí significativo para sus propios módulos, especialmente durante el desarrollo. Es la opción de reload()
un módulo. Considere esto:
from module import func ... reload(module) # func still points to the old code
Por otro lado
import module ... reload(module) # module.func points to the new code
En cuanto a la velocidad … .
estamos importando solo la función que se necesita en lugar de importar el módulo completo (que contiene más funciones inútiles que Python perderá tiempo importándolas)
Ya sea que importe un módulo o una función de un módulo, Python analizará todo el módulo. De cualquier forma, se importa el módulo. «Importar una función» no es más que vincular la función a un nombre. De hecho, import module
es menos trabajo para el intérprete que from module import func
.
Comentarios
- reload () era una función incorporada en Python 2; ese ya no es el caso de Python 3.
- ¿Pensé que también había implicaciones que ver con las dependencias de importación circular?
Respuesta
Utilizo from import
s siempre que mejore la legibilidad. Por ejemplo, prefiero (los puntos y comas son solo para ahorrar espacio aquí):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
en lugar de:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Este último es más difícil de leer (y escribir) para mí porque contiene mucha información redundante. Además, es útil saber de antemano qué partes de un módulo estoy usando.
Prefiero las import
normales si estoy usando muchos de nombres cortos de un módulo:
import sys sys.argv; sys.stderr; sys.exit()
O si un nombre es tan genérico que no tiene sentido fuera de su espacio de nombres:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Comentarios
- Esta es mi respuesta favorita. ‘ Explícito es mejor que implícito ‘ a veces entra en conflicto con la legibilidad, la simplicidad y DRY. Especialmente cuando se usa un marco como Django.
Responder
En mi opinión, usar mejora la legibilidad. Al revisar el código de Python, me gusta ver de dónde viene la función o clase dada, justo donde se usa. Me evita tener que desplazarme hasta la parte superior del módulo para obtener esa información.
En cuanto a los nombres largos de los módulos, solo uso la palabra clave as
y les doy breves alias:
import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
Como excepción, siempre uso la notación from module import something
cuando trato con la __future__
. No puede hacerlo de otra manera cuando desea que todas las cadenas sean unicode por defecto en Python 2, por ejemplo,
from __future__ import unicode_literals from __future__ import print_function
Comentarios
- ¡Amén! » importar como » es una combinación ganadora 🙂
Responder
Aunque import sys
y from sys import agrv
ambos importan el módulo sys
completo, el último usa el enlace de nombre, por lo que solo el módulo argv
es accesible para el resto del código.
Para algunas personas, este sería el estilo preferido, ya que solo hace accesible la función que indicó explícitamente.
Sin embargo, introduce posibles conflictos de nombres. ¿Qué pasaría si tuviera otro módulo llamado argv
? Tenga en cuenta que también puede importar explícitamente la función y cambiar el nombre con from sys import argv as sys_argv
, una convención que cumple con la importación explícita y es menos probable que dé espacio de nombre colisiones.
Comentarios
- Entonces, ¿cómo es
if sys_argv:
algo mejor queif sys.argv:
? Sé lo que significa la segunda declaración, no tengo idea de lo que significa la primera forma sin retroceder a la extraña importancia.
Respuesta
Recientemente me hice esta pregunta. Calculé los diferentes métodos.
biblioteca de solicitudes
def r(): import requests return "hello" timeit r() # output: 1000000 loops, best of 3: 1.55 µs per loop def rg(): from requests import get return "hello" timeit rg() # output: 100000 loops, best of 3: 2.53 µs per loop
biblioteca beautifulsoup
def bs(): import bs4 return "hello" timeit bs() # output: 1000000 loops, best of 3: 1.53 µs per loop def be(): from bs4 import BeautifulSoup return "hello" timeit be() # output: 100000 loops, best of 3: 2.59 µs per loop
biblioteca json
def js(): import json return "hello" timeit js() # output: 1000000 loops, best of 3: 1.53 µs per loop def jl(): from json import loads return "hello" timeit jl() # output: 100000 loops, best of 3: 2.56 µs per loop
biblioteca sys
def s(): import sys return "hello" timeit s() # output: 1000000 loops, best of 3: 1.55 µs per loop def ar(): from sys import argv return "hello" timeit ar() # output: 100000 loops, best of 3: 2.87 µs per loop
Parece me dice que hay una ligera diferencia en el rendimiento.
Comentarios
- Está agregando una búsqueda de atributos. Para comparar
import module
confrom module import name
correctamente, agrega la búsqueda de ese nombre a laimport module
caso. P.ej. agregue la líneasys.argv
a laar
prueba, etc. Todavía habrá una diferencia, porque el trabajo realizado es levemente diferente, ya que se genera un código de bytes diferente y se ejecutan diferentes rutas de código. - Tenga en cuenta que abordo directamente esa diferencia en mi respuesta; habrá una diferencia entre usar
import sys
y luego usarsys.argv
miles de tiempo en un bucle frente afrom sys import argv
luego usando soloargv
. Pero no ‘ t. Para las cosas que hace solo una vez a nivel global de su módulo, realmente debería optimizar la legibilidad, no las diferencias microscópicas en los tiempos. - ¡Ahhhh! ¡Y pensé que estaba en algo! 🙂 Solo hojeé tu respuesta. Parece que salté el arma en ese. Se siente bien ser humilde.
Responder
Ver fragmentos de código publicados, importar módulos completos y hacer referencia a module.function
es prácticamente el estándar, al menos para los módulos estándar. La única excepción parece ser datetime
from datetime import datetime, timedelta
para que pueda decir datetime.now()
en lugar de datetime.datetime.now()
.
Si le preocupa el rendimiento, siempre puede decir (por ejemplo)
argv = sys.argv
y luego haga su código de rendimiento crítico ya que la búsqueda del módulo ya está hecha. Sin embargo, aunque esto funcionará con funciones / métodos, la mayoría de los IDE se confundirán y no mostrarán (por ejemplo) un enlace / firma de origen para la función cuando se asigne a una variable.
Respuesta
Solo quiero agregar eso si haces algo como
from math import sin
(o cualquier otra biblioteca integrada como sys
o posix
), entonces sin
incluirse en la documentación de su módulo (es decir, cuando haga >>> help(mymodule)
o $ pydoc3 mymodule
. Para evitar esto, importe usando:
import math from math import sin as _sin
PD: una biblioteca integrada es aquella que se compila a partir de código C y se incluye con Python. argparse
, os
y io
no son paquetes integrados
from … import …
en Python