Python: A che serve utilizzare "import"?

8

Non sono molto chiaro su questo aspetto. Supponiamo che tu abbia un sacco di file .py che sono i loro moduli separati.

Perché ogni file .py deve importare gli altri quando usano quella classe? O loro? Perché ero abbastanza sicuro che altri linguaggi (Java, ad esempio), non richiedessero l'importazione quando ci si riferiva a classi / file nella stessa directory. Potrei sbagliarmi.

    
posta Kaitlyn Mcmordie 30.12.2011 - 07:58
fonte

5 risposte

8

In poche parole, è così che è stato progettato. Hai citato Java come esempio contrario: i progettisti del linguaggio Java volevano rendere il caricamento di classe un po 'implicito, quindi controllano la stessa directory prima di lanciare ClassNotFound . Al di fuori di questo devi qualificarti, proprio come in Python.

Come ha detto Tom Anderson, C fa la stessa cosa di Python, ed è un linguaggio compilato. Forse la natura interpretata della lingua ha qualcosa a che fare con la decisione finale (per le prestazioni, l'esplicitazione, ecc.), Ma alla fine spetta allo sviluppatore.

    
risposta data 30.12.2011 - 14:26
fonte
3

Poiché python è interpretato, tutto ciò che importa è disponibile al prompt. Java (e C ++) hanno una fase di compilazione e collegamento che può cercare e includere solo le funzioni utilizzate

Se tutto fosse importato automaticamente, ci sarebbero migliaia di funzioni e variabili e sarebbe impossibile scrivere qualsiasi cosa senza scontrarsi con uno.

edit: Ok è un po 'più che solo compilato vs interpretato. Python è inteso come un linguaggio "batterie incluse" - ci sono librerie disponibili per fare quasi tutto. Dal momento che utilizzerai solo una piccola parte di questi, è necessario un modo per organizzarli in modo da includere solo quelli di cui hai bisogno.

L'importazione dalla sintassi è intelligente perché puoi importare l'intera libreria e mantenere nomi completamente qualificati come Java o puoi importare funzioni specifiche (o tutte le funzioni) nello spazio dei nomi locale

>>>import math
>>> math.sin(0)  #no confusion with any other 'sin'

>>> from math import sin  # or import *
>>> sin(0) # makes equations with sin shorter and simpler

La seconda ragione è particolarmente importante in un linguaggio dinamico come Python. Dato che non devi definire le variabili prima di usarle, sarebbe difficile per l'ambiente funzionare se sin è la funzione matematica o una tua variabile in un interprete.

    
risposta data 30.12.2011 - 08:09
fonte
1

Immagina di avere questo codice in python:

foo = MyObject()
fo.bar()

Ovviamente, abbiamo un errore di battitura e fo avrebbe dovuto essere foo . In questo momento python dice:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'fo' is not defined

Ma con il caricamento di classe implicito potrebbe dire:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named fo

che sarebbe fonte di confusione. Peggio ancora, se hai sbagliato a digitare un nome di variabile che era il nome di un modulo, potresti ottenere un errore ancora più confuso mentre tentavi di trattare quel modulo come se fosse la tua variabile. Python non può sapere se qualcosa è un nome di classe, oggetto o altro.

Java, d'altra parte, credo possa dire dalla sintassi se un certo identificatore si riferisce a una classe o qualcos'altro. Pertanto non ha alcun problema con la produzione di un messaggio di errore appropriato.

Nel complesso, rientra nella filosofia di Python di essere espliciti piuttosto che impliciti. Pensano che sia meglio importare esplicitamente un modulo piuttosto che importarlo automaticamente. Il problema del messaggio di errore è un fattore che gioca nella decisione.

Alcuni hanno suggerito che ci sarebbe un grande costo di runtime per le importazioni implicite. Io non la penso così Quello che succede è qualcosa del genere:

  1. LOAD_GLOBAL opcode richiamato con nome "foo"
  2. dizionario globale controllato per "pippo"
  3. builtins dizionario controllato per "foo"
  4. Se viene trovato, memorizza in globals e continua su
  5. Se non viene trovato, sollevare NameError

Per supportare il caricamento implicito del modulo, potremmo fare:

  1. LOAD_GLOBAL opcode richiamato con nome "foo"
  2. dizionario globale controllato per "pippo"
  3. builtins dizionario controllato per "foo"
  4. se il precedente non funziona, prova import foo
  5. Se viene trovato, memorizza in globals e continua su
  6. Se non viene trovato, sollevare NameError

La prima volta che il modulo viene utilizzato, ci vorrebbe un po 'di più perché deve prima cercare attraverso altri dizionari. Ma questa è solo la prima volta e non dovrebbe essere significativa in termini di intero runtime del programma.

Ci sarebbe un costo significativo, nel caso di nomi di variabili con errori di ortografia. Quando si imbattono, Python perderebbe tempo a leggere il disco cercando di trovare il modulo. Ma se ciò accade il tuo programma sta per morire comunque con un traceback e la performance non è un grosso problema.

    
risposta data 31.12.2011 - 01:26
fonte
1

Ci sono alcune importanti differenze tra Python e Java; mentre Java ha una regola "una classe per file", Python no. Inoltre, non tutto in Python è una classe.

Quindi un modulo può avere classi, funzioni e semplicemente vecchie variabili - di solito tutte correlate in qualche modo (come le funzioni casuali in random , le routine matematiche in math , i contstants di stringa in string , ecc. ).

Se vuoi accedere a qualsiasi classe / funzione / variabile da un particolare modulo, devi prima importarlo.

Perché questa è una buona cosa?

  • Mantiene puliti gli spazi dei nomi dei moduli (non ingombri di nomi che non userete mai)
  • È più facile rintracciare il modulo appropriato quando qualcosa va storto
  • Ti permette di usare i nomi senza timore di un errore, perché il nome è in uso, o di clobbering del nome già in uso (puoi avere math.sin e le tue funzioni sin )
  • Aiuta a chiarire la struttura del programma.
risposta data 10.01.2012 - 22:37
fonte
1

Uno dei concetti più importanti in Python è quello dei namespace (fai import this al prompt qualche tempo per scoprire cosa sono gli altri). So che i namespace esistono anche in altre lingue, ma in Python si ha accesso solo allo spazio dei nomi corrente, che è ciò che è definito nel modulo corrente. Per accedere ad altri identificatori, devi importarli nello spazio dei nomi corrente: importando il loro modulo contenente (la sintassi import foo ) oi nomi stessi ( from foo import bar ).

    
risposta data 10.01.2012 - 22:59
fonte

Leggi altre domande sui tag