Qual è la relazione tra scope e namespace in Python?


12

In molte risorse ho scoperto che "scope" e "namespace" sono usati in modo intercambiabile, il che sembra un po 'confuso poiché significano cose diverse.

  • L'ambito definisce la regione del codice in cui è disponibile un nome.
  • La regola LEGB definisce il modo in cui i nomi vengono cercati.
  • Lo spazio dei nomi è un luogo in cui si cercano i nomi.

Poi ho letto:

  • "i nomi sono associati a uno spazio dei nomi in base a dove sono assegnati ..." (che credo sia il problema con gli ambiti nello scoping lessicale).
  • "Le funzioni aggiungono un ulteriore livello di spazio dei nomi ai tuoi programmi" [ rif. ] (non aggiungono un ambito locale aggiuntivo?)
  • "tutti i nomi assegnati all'interno di una definizione di funzione vengono inseriti nell'ambito locale (lo spazio dei nomi associato alla chiamata di funzione)."
  • "ambito globale, ovvero uno spazio dei nomi in cui vivono le variabili create (assegnate) al livello superiore del file del modulo."

* tutte le citazioni sono tratte dall'apprendimento di Python 5a edizione ch17

Gli spazi dei nomi in Python sono il modo in cui vengono implementati gli ambiti? Sono la stessa cosa? Qualcuno può illuminarmi?


1
Potresti fornire riferimenti per le virgolette - Ne ho trovato uno, ma non l'altro.
jonrsharpe,

1
Gli spazi dei nomi sono solo un tipo di ambito. Vedi stackoverflow.com/questions/291978/…
Robert Harvey,

Risposte:


16

Uno spazio dei nomi è un dizionario che associa i nomi (come stringhe) ai valori. Quando svolgi un compito, ad esempio a = 1, stai mutando uno spazio dei nomi. Quando fai un riferimento, ad esempio print(a), Python guarda attraverso un elenco di spazi dei nomi per cercare di trovarne uno con il nome come chiave.

Un ambito definisce quali spazi dei nomi verranno cercati e in quale ordine. L'ambito di qualsiasi riferimento inizia sempre nello spazio dei nomi locale e si sposta verso l'esterno fino a raggiungere lo spazio dei nomi globale del modulo, prima di passare allo builtins(spazio dei nomi che fa riferimento alle funzioni e alle costanti predefinite di Python, come rangee getattr), che è la fine della riga .

Immagina di avere una funzione denominata inner, nidificata all'interno di una funzione globale denominata outere che innercontiene un riferimento a un nome. Python prima guarda nello innerspazio dei nomi. Se il nome non è presente, Python cerca nello outerspazio dei nomi. Se fallisce, Python prova lo globalspazio dei nomi del modulo , quindi lo builtinspazio dei nomi, eventualmente lanciando un NameErrorse il nome non viene trovato.

Quando diciamo che si xtrova nello spazio dei nomi di una funzione, intendiamo che è definito lì, localmente all'interno della funzione. Quando diciamo che xrientra nell'ambito della funzione, intendiamo xsia nello spazio dei nomi della funzione o in uno qualsiasi degli spazi dei nomi esterni che lo spazio dei nomi della funzione è annidato all'interno.

Ogni volta che si definisce una funzione, si crea un nuovo spazio dei nomi e un nuovo ambito. Lo spazio dei nomi è il nuovo hash locale di nomi. L'ambito è la catena implicita di spazi dei nomi che inizia nel nuovo spazio dei nomi, quindi si fa strada attraverso tutti gli spazi dei nomi esterni (ambiti esterni), fino allo spazio dei nomi globale (l'ambito globale) e fino ai builtin.

I termini possono essere usati quasi in modo intercambiabile, ma non perché significano la stessa cosa; è perché si sovrappongono molto in ciò che implicano.


3
"I termini possono essere usati quasi in modo intercambiabile, ma non perché significano la stessa cosa; è perché si sovrappongono molto in ciò che implicano."
Nikos,

2
Questa risposta è giusta nello spirito, ma sbagliata nei dettagli. Le classi in Python non introducono un nuovo spazio dei nomi, motivo per cui gli attributi di classe devono essere qualificati con il nome della classe e perché gli attributi di istanza devono essere qualificati con il nome dell'istanza. I livelli di spazio dei nomi in Python da interno a esterno sono Local, Enclosing, Global e Built-in. Una classe può essere definita a qualsiasi di questi livelli, ma i membri di una classe devono sempre essere qualificati.
Rob Smallshire,

Hai ragione. Le lezioni non funzionano come ho detto. Pensavo che creassero un ambito lessicale come una funzione, ma non lo fanno. Per favore aggiorna la risposta se hai tempo, altrimenti lo farò ad un certo punto. Grazie.
Carl Smith,

1
+1 Risposta brillante, incapsulando tale sottigliezza in modo così economico. L'ho trovato molto utile, grazie!
cercatore

1
"Uno spazio dei nomi è un hash di nome, coppie di valori, molto simile a un dizionario Python" - Sono abbastanza sicuro che gli spazi dei nomi siano memorizzati come dizionari Python. Ad esempio, è possibile modificare lo spazio dei nomi globale chiamando globals (), che consente di modificare direttamente il dizionario per associare oggetti e nomi: ad esempio globals () [name] = "object". Ottima risposta altrimenti.
Evan Rosica,

4

C'è un eccellente articolo sugli spazi dei nomi di Python qui . Per citare la parte pertinente per rispondere alla tua domanda sul riferimento tra ambiti e spazi dei nomi:

Un ambito fa riferimento a una regione di un programma da cui è possibile accedere a uno spazio dei nomi senza prefisso.

Ad esempio, immagina un semplice programma di fustellatura:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll ha un proprio spazio dei nomi , ma anche i nomi nello spazio dei nomi del modulo rientrano nell'ambito .


@CarlSmith nota che la prima documentazione di Python dice la stessa cosa: "Un ambito è una regione testuale di un programma Python in cui uno spazio dei nomi è direttamente accessibile." Qui accessibile direttamente "significa che un riferimento non qualificato a un nome tenta di trovare il nome nello spazio dei nomi ".
jonrsharpe,

@CarlSmith a parte l'ambito aggiuntivo non locale / che racchiude l'ambito, è cambiato molto? Penso che stiamo dicendo la stessa cosa: uno spazio dei nomi contiene i nomi e i valori e l'ambito ti dice quali spazi dei nomi sono accessibili.
jonrsharpe,

Ho cancellato i miei vecchi commenti.
Carl Smith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.