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 eseguire package.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 (specialmente import 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 di if 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 una leggera differenza nelle prestazioni.

Commenti

  • Stai aggiungendo una ricerca di attributi. Per confrontare import module con from module import name correttamente, aggiungi la ricerca del nome a import module caso. Per esempio. aggiungi la riga sys.argv al ar 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 di sys.argv migliaia di volte in un ciclo e from sys import argv quindi utilizzando solo argv. 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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *