Ho sempre utilizzato questo metodo:
from sys import argv
e utilizza argv
solo con argv . Ma esiste una convenzione di utilizzare questo:
import sys
e di utilizzare argv di sys.argv
Il secondo metodo rende il codice auto documentato e io (davvero) ci aderisco. Ma il motivo per cui preferisco il primo metodo è che è veloce perché stiamo importando solo la funzione che è necessaria piuttosto che importare lintero modulo (che contiene più funzioni inutili che Python sprecherà tempo a importarle). Nota che ho bisogno solo di argv e tutte le altre funzioni di sys sono inutili per me.
Quindi le mie domande sono. Il primo metodo rende davvero veloce lo script? Qual è il metodo preferito di più? Perché?
Commenti
Risposta
Limportazione del modulo non spreca nulla ; il modulo è sempre completamente importato (nella mappatura sys.modules
), quindi se utilizzi import sys
o from sys import argv
non fa alcuna differenza.
Lunica differenza tra le due istruzioni è il nome associato; import sys
lega il nome sys
al modulo (quindi sys
-> sys.modules["sys"]
), mentre from sys import argv
si lega un nome diverso, argv
, che punta direttamente allattributo contenuto allinterno del modulo (quindi argv
-> sys.modules["sys"].argv
). Il resto di th Il modulo sys
è ancora lì, indipendentemente dal fatto che tu usi qualcosaltro dal modulo o meno.
Non cè nemmeno differenza di prestazioni tra i due approcci. Sì, sys.argv
deve cercare due cose; deve cercare sys
nel tuo spazio dei nomi globale (trova il modulo), quindi cercare lattributo argv
. E sì, utilizzando from sys import argv
puoi saltare la ricerca dellattributo, poiché hai già un riferimento diretto allattributo. Ma listruzione import
deve ancora funzionare, cerca lo stesso attributo durante limportazione e “dovrai sempre e solo utilizzare argv
una volta . Se dovessi usare argv
migliaia di volte in un ciclo potrebbe forse fare la differenza, ma in questo caso specifico non lo fa .
La scelta tra luna o laltra dovrebbe essere basata invece sullo stile di codifica .
In un modulo grande , Io “avrei certamente usato import sys
; la documentazione del codice è importante e lutilizzo di sys.argv
da qualche parte in un modulo di grandi dimensioni rende molto più chiaro a cosa ti riferisci rispetto a argv
.
Se lunico posto in cui utilizzi argv
è in un "__main__"
blocco per chiamare un main()
, usa assolutamente from sys import argv
se ti senti più felice a riguardo:
if __name__ == "__main__": from sys import argv main(argv)
I “d uso ancora import sys
anche lì. A parità di condizioni (e sono, esattamente, in termini di prestazioni e numero di caratteri usati per scriverlo) , per me è solo più facile da vedere.
Se stai importando qualcosa di altro , forse entra in gioco la performance. Ma solo se usi un nome specifico in un molte volte , ad esempio in un ciclo critico. Ma la creazione di un nome locale (allinterno di una funzione) sarà ancora più veloce:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Commenti
- Cè anche la situazione in cui hai un pacchetto con sottopacchetti o moduli che espone un attributo di uno di quei sottopacchetti / moduli nel pacchetto di primo livello. Lutilizzo di
from...import
ti consente di eseguirepackage.attribute
anzichépackage.subpackage_or_module.attribute
, che può essere utile se hanno raggruppamenti logici o concettuali allinterno del pacchetto ma vogliono rendere le cose un po più convenienti per gli utenti del pacchetto. (numpy
fa qualcosa del genere, credo.) - In django ci sono tantissimi posti in cui cose come
from django.core.management.base import BaseCommand
sono migliori e qualsiasi altra cosa (specialmenteimport django
) porterebbe a codice illeggibile. Quindi, sebbene questa risposta mi piaccia, penso che ci siano alcune librerie (e soprattutto alcuni framework) in cui la convenzione è di violare limportazione nuda.Come sempre, usa il tuo giudizio su ciò che è meglio in una data situazione. Ma sbagli sul lato dellesplicito (in altre parole sono daccordo per la maggior parte). - @JAB: puoi ancora usare
import ... as
per trovare il pacchetto da un nome diverso:import package.subpackage_or_module as shortname
.from parent import sub
fa, essenzialmente, la stessa cosa. -
so wether you use import sys or from sys import argv makes no odds
questo sembra non essere il caso di IDLE. solo importare il modulo non importa le sue funzioni e posso chiamarlo nella shell IDLE solo da < module >. < function > name - @Suncatcher: leggi la mia risposta per intero. La frase che citi parla di quanto viene importato, non di quale nome è associato. Questo ‘ è trattato altrove nella risposta.
Risposta
Ci sono due ragioni a favore dellutilizzo di import module
invece di from module import function
.
Il primo è lo spazio dei nomi. Limportazione di una funzione nello spazio dei nomi globale rischia di creare collisioni di nomi.
Il secondo non è rilevante per i moduli standard, ma significativo per i propri moduli, specialmente durante lo sviluppo. È lopzione reload()
un modulo. Considera questo:
from module import func ... reload(module) # func still points to the old code
Daltra parte
import module ... reload(module) # module.func points to the new code
Per quanto riguarda la velocità .. .
stiamo importando solo la funzione necessaria invece di importare lintero modulo (che contiene più funzioni inutili che Python sprecherà tempo a importarle)
Sia che importi un modulo o importi una funzione da un modulo, Python analizzerà lintero modulo. In entrambi i casi il modulo viene importato. “Importare una funzione” non è altro che legare la funzione a un nome. Infatti import module
richiede meno lavoro per linterprete di from module import func
.
Commenti
- reload () era un builtin di Python 2; non è più il caso di Python 3.
- Pensavo che ci fossero anche implicazioni a che fare con le dipendenze di importazione circolare?
Risposta
Uso from import
ogni volta che migliora la leggibilità. Ad esempio, preferisco (i punti e virgola servono solo per risparmiare spazio qui):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
invece di:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Questultimo è più difficile da leggere (e scrivere) per me perché contiene così tante informazioni ridondanti. Inoltre, è utile sapere in anticipo quali parti di un modulo sto utilizzando.
Preferisco i import
regolari se ne uso molti di nomi brevi da un modulo:
import sys sys.argv; sys.stderr; sys.exit()
O se un nome è così generico da non avere senso al di fuori del suo spazio dei nomi:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Commenti
- Questa è la mia risposta preferita. ‘ Esplicito è meglio di implicito ‘ a volte è in conflitto con leggibilità, semplicità e DRY. Soprattutto quando si utilizza un framework come Django.
Rispondi
A mio parere, utilizzando il normale import
migliora la leggibilità. Durante la revisione del codice Python mi piace vedere da dove proviene la funzione o classe data proprio dove viene utilizzata. Mi evita di scorrere fino allinizio del modulo per ottenere quelle informazioni.
Per quanto riguarda i nomi lunghi dei moduli, uso semplicemente la parola chiave as
e li do brevi 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()
Come eccezione uso sempre la notazione from module import something
quando mi occupo di __future__
modulo. Non puoi farlo in un altro modo quando vuoi che tutte le stringhe siano unicode per impostazione predefinita in Python 2, ad esempio
from __future__ import unicode_literals from __future__ import print_function
Commenti
- Amen! ” import as ” è una combinazione vincente 🙂
Risposta
Sebbene import sys
e from sys import agrv
entrambi importano lintero modulo sys
, questultimo utilizza lassociazione del nome in modo che solo il modulo argv
sia accessibile al resto del codice.
Per alcune persone questo sarebbe lo stile preferito poiché rende accessibile solo la funzione che hai esplicitamente dichiarato.
Tuttavia introduce potenziali conflitti di nome. E se avessi un altro modulo chiamato argv
? Nota che puoi anche importare esplicitamente la funzione e rinominarla con from sys import argv as sys_argv
, una convenzione che soddisfa limportazione esplicita ed è meno probabile che dia spazio ai nomi collisioni.
Commenti
- Allora, in che modo
if sys_argv:
è migliore diif sys.argv:
? So cosa significa la seconda affermazione, non ho idea di cosa significhi la prima forma senza tornare indietro allimportanza bizzarra.
Risposta
Recentemente mi sono posto questa domanda a me stesso. Ho sincronizzato i diversi metodi.
richiede libreria
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
libreria 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
libreria 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
libreria 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
Sembra me che cè una leggera differenza nelle prestazioni.
Commenti
- Stai aggiungendo una ricerca di attributi. Per confrontare
import module
confrom module import name
correttamente, aggiungi la ricerca del nome aimport module
caso. Per esempio. aggiungi la rigasys.argv
alar
test e così via. Ci sarà ancora una differenza, perché il lavoro svolto è leggermente diverso, poiché viene generato un bytecode diverso e vengono eseguiti codepath diversi. - Nota che affronto direttamente questa differenza nella mia risposta; ci sarà una differenza tra lutilizzo di
import sys
e lutilizzo disys.argv
migliaia di volte in un ciclo efrom sys import argv
quindi utilizzando soloargv
. Ma non ‘ t. Per le cose che fai una sola volta a livello globale del tuo modulo, dovresti davvero ottimizzare per la leggibilità, non per differenze microscopiche nei tempi. - Ahhhh! E pensavo di aver capito qualcosa! 🙂 Ho solo scremato la tua risposta. Sembra che ho saltato la pistola su quello. È bello essere umiliato.
Risposta
Guardando frammenti di codice pubblicati, importando interi moduli e facendo riferimento a module.function
è praticamente lo standard, almeno per i moduli standard. Lunica eccezione sembra essere datetime
from datetime import datetime, timedelta
quindi puoi dire datetime.now()
anziché datetime.datetime.now()
.
Se sei preoccupato per il rendimento, puoi sempre dire (ad esempio)
argv = sys.argv
e quindi eseguire il codice critico per le prestazioni poiché la ricerca del modulo è già stata eseguita. Tuttavia, sebbene questo funzioni con funzioni / metodi, la maggior parte degli IDE si confondono e (ad esempio) non visualizzano un link / firma sorgente per la funzione quando è assegnata a una variabile.
Risposta
Voglio solo aggiungerla se fai qualcosa di simile
from math import sin
(o qualsiasi altra libreria incorporata come sys
o posix
), quindi sin
essere incluso nella documentazione per il tuo modulo (ad esempio quando fai >>> help(mymodule)
o $ pydoc3 mymodule
. Per evitare ciò, importa utilizzando:
import math from math import sin as _sin
PS: una libreria incorporata è quella compilata da codice C e inclusa con Python. argparse
, os
e io
non sono pacchetti integrati
from … import …
sintassi in Python