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 hacer package.attribute en lugar de package.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 (especialmente import 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 que if 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 con from module import name correctamente, agrega la búsqueda de ese nombre a la import module caso. P.ej. agregue la línea sys.argv a la ar 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 usar sys.argv miles de tiempo en un bucle frente a from sys import argv luego usando solo argv. 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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *