'import module' vs. 'from module import function'

126

Ho sempre utilizzato questo metodo:

from sys import argv

e usa argv con solo argv . Ma esiste una convenzione per l'uso di questo:

import sys

e utilizzo di argv di sys.argv

Il secondo metodo rende il codice auto-documentato e I (veramente) vi aderisce. Ma la ragione per cui preferisco il primo metodo è che è veloce perché stiamo importando solo la funzione che è necessaria piuttosto che importare l'intero modulo (che contiene altre 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 la sceneggiatura? Quale metodo è preferito di più? Perché?

    
posta Santosh Kumar 18.02.2013 - 06:43
fonte

8 risposte

160

L'importazione del modulo non spreca nulla ; il modulo è sempre fully importato (nella mappatura sys.modules ), quindi se usi import sys o from sys import argv non fa alcuna differenza.

L'unica differenza tra le due affermazioni è quale nome è associato; import sys lega il nome sys al modulo (quindi sys - > sys.modules['sys'] ), mentre from sys import argv lega un nome diverso, argv , puntando dritto all'attributo contenuto all'interno del modulo (quindi argv - > sys.modules['sys'].argv ). Il resto del modulo sys è ancora lì, indipendentemente dal fatto che tu usi qualcos'altro dal modulo o meno.

Non vi è inoltre alcuna 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 cerca l'attributo argv . E sì, usando from sys import argv puoi saltare la ricerca degli attributi, dato che hai già un riferimento diretto all'attributo. Ma l'istruzione import deve ancora funzionare, cerca lo stesso attributo durante l'importazione e dovrai sempre usare argv una volta . Se dovessi usare argv migliaia di volte in un ciclo, potrebbe forse fare la differenza, ma in questo caso specifico in realtà non lo è.

La scelta tra l'una o l'altra quindi, dovrebbe essere basata su stile di codifica , invece.

In un modulo grande , certamente utilizzerei import sys ; la documentazione del codice è importante e l'utilizzo di sys.argv da qualche parte in un modulo di grandi dimensioni rende molto più chiaro a cosa ti stai riferendo che solo argv mai.

Se l'unica posizione che usi argv è in un blocco '__main__' per chiamare una funzione main() , usa assolutamente from sys import argv se ti senti più felice a tale proposito:

if __name__ == '__main__':
    from sys import argv
    main(argv)

Userei ancora import sys lì da solo. A parità di condizioni (e sono esattamente, in termini di prestazioni e numero di caratteri usati per scriverlo), per me è solo più facile da guardare.

Se stai importando qualcosa altro , allora forse le prestazioni entrano in gioco. Ma solo se usi un nome specifico in un modulo molte volte , in un ciclo critico per esempio. Ma poi creare un nome locale (all'interno di una funzione) sarà ancora più veloce:

 import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)
    
risposta data 18.02.2013 - 19:17
fonte
38

Ci sono due ragioni a favore dell'uso di import module piuttosto che from module import function .

Il primo è lo spazio dei nomi. L'importazione di una funzione nello spazio dei nomi globale rischia di danneggiare il nome.

Il secondo non è rilevante per i moduli standard, ma è significativo per i propri moduli, specialmente durante lo sviluppo. È l'opzione per reload() un modulo. Considera questo:

from module import func
...
reload(module)
# func still points to the old code

D'altra parte

import module
...
reload(module)
# module.func points to the new code

Per quanto riguarda la velocità ...

we are importing only the function that is needed rather than import the whole module (which contains more useless functions which python will waste time importing them)

Sia che importi un modulo o che importi una funzione da un modulo, Python analizzerà l'intero modulo. In entrambi i casi, il modulo viene importato. "Importare una funzione" non è altro che legare la funzione a un nome. Infatti import module è meno lavoro per interprete di from module import func .

    
risposta data 18.02.2013 - 10:09
fonte
17

Secondo me, l'uso regolare di import migliora la leggibilità. Durante la revisione del codice Python mi piace vedere dove la funzione o classe data proviene proprio da dove viene usata. Mi salva dallo scorrere fino alla cima del modulo per ottenere quelle informazioni.

Come per i nomi di moduli lunghi, uso solo la parola chiave as e fornisco loro 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 gestisco il modulo __future__ . Non puoi farlo in un altro modo quando vuoi che tutte le stringhe siano unicode per impostazione predefinita in Python 2, ad es.

from __future__ import unicode_literals
from __future__ import print_function
    
risposta data 04.03.2015 - 18:25
fonte
16

Uso from import s 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()

Quest'ultimo è 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 usando.

Preferisco regolare import s se sto usando molti 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
    
risposta data 18.02.2013 - 19:42
fonte
4

Sebbene import sys e from sys import agrv entrambi importino l'intero modulo sys , quest'ultimo usa il nome binding in modo che solo il modulo argv sia accessibile al resto del codice.

Per alcune persone questo sarebbe lo stile preferito dal momento che rende solo accessibile la funzione che hai esplicitamente dichiarato.

Presenta tuttavia potenziali conflitti di nome. E se avessi un altro modulo chiamato argv ? Nota puoi anche importare esplicitamente la funzione e rinominare con from sys import argv as sys_argv , una convenzione che soddisfa l'importazione esplicita ed è meno probabile che abbia dato collisioni nello spazio del nome.

    
risposta data 20.02.2013 - 05:49
fonte
1

Recentemente ho fatto questa domanda a me stesso. Ho programmato i diversi metodi.

richiede una 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

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

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

Mi sembra che ci sia una leggera differenza di prestazioni.

    
risposta data 07.01.2015 - 22:23
fonte
-1

Guardando i frammenti di codice pubblicati, l'importazione di interi moduli e il riferimento a module.function è praticamente lo standard, almeno per i moduli standard. L'unica eccezione sembra essere datetime

from datetime import datetime, timedelta

quindi puoi dire datetime.now() anziché datetime.datetime.now() .

Se sei preoccupato per le prestazioni, puoi sempre dire (ad esempio)

argv = sys.argv

e quindi esegui il tuo codice critico delle prestazioni poiché la ricerca del modulo è già stata eseguita. Tuttavia, sebbene funzioni con funzioni / metodi, la maggior parte degli IDE si confondono e non visualizzeranno (ad esempio) un link / firma sorgente per la funzione quando è assegnata a una variabile.

    
risposta data 03.06.2016 - 18:01
fonte
-2

Voglio solo aggiungere che se fai qualcosa di simile

from math import sin

(o qualsiasi altra libreria incorporata come sys o posix ), quindi sin sarà inclusa nella documentazione del tuo modulo (cioè quando fai >>> help(mymodule) o $ pydoc3 mymodule . Per evitare questo , importa usando:

import math
from math import sin as _sin

PS: una libreria incorporata è una libreria compilata dal codice C e inclusa in Python. argparse , os e io non sono pacchetti integrati

    
risposta data 03.09.2017 - 07:33
fonte

Leggi altre domande sui tag