Gli spazi dei nomi

Introduzione

Che cosa è uno spazio dei nomi? È abbastanza difficile rispondere alla domanda, non tanto perché si tratti di un argomento particolarmente complicato, ma perché ogni linguaggio lo intende in termini diversi. Il concetto è semplice: uno spazio dei nomi è un'area o una regione all'interno di un programma in cui un nome (di variabile, di classe, ecc.) è valido.

Il concetto è stato introdotto perché i primi linguaggi di programmazione (come il BASIC) avevano soltanto variabili globali ovvero variabili che erano visibili da qualunque parte del programma, anche dall'interno di funzioni. Questo rendeva assai difficile la manutenzione di grandi programmi dato che era assai facile che una parte di programma potesse modificare una variabile senza che altre parti del programma potessero tenerne conto, un fenomeno detto side effect [effetto collaterale, N.d.t]. Per risolvere questo problema i linguaggi più recenti (inclusi i BASIC moderni) hanno introdottto il concetto di spazio dei nomi. (il C++ ha portato il concetto alle estreme conseguenze consentendo al programmatore di creare spazi dei nomi propri in qualunque punto di un programma. Questo è utile per gli sviluppatori di librerie che possono avere la necessità di mantenere nomi di funzioni univoci anche quando le loro sono usate congiuntamente a librerie sviluppate da altri).

L'approccio di Python

In Python ogni modulo crea il proprio spazio dei nomi. Per accedere a tali nomi dobbiamo precederli con il nome del modulo oppure importare esplicitamente i nomi che vogliamo usare all'interno dello spazio dei nomi del nostro modulo. In questo non c'è niente di nuovo: lo abbiamo già fatto con i moduli sys e string. In un certo senso anche la definizione di una classe crea il proprio spazio dei nomi. Quindi per accedere ad un metodo o ad un attributo di una classe dobbiamo premettere il nome della variabile di istanza o della classe.

In Python ci sono sempre soltanto 3 spazi dei nomi [in inglese scope, N.d.t.]:

  1. Lo spazio dei nomi locale: i nomi definiti all'interno di una funzione o di un metodo.
  2. Lo spazio del modulo: i nomi definiti all'interno di un file
  3. Lo spazio "builtin": i nomi definiti all'interno di Python che sono sempre disponibili.

Fin qui tutto bene. Ma cosa accade quando variabili di differenti spazi dei nomi hanno lo stesso nome? O quando si fa riferimento ad un nome non contenuto nello spazio corrente? Vediamo innanzitutto il primo caso: se una funzione fa riferimento ad una variabile di nome X ed esiste un X all'interno della funzione (spazio locale) allora questa è la variabile a cui si fa riferimento e che viene usata da Python. È compito del programmatore evitare conflitti fra i nomi in modo che all'interno di una funzione non siano usate una variabile dello spazio del modulo ed una dello spazio locale con lo stesso nome: se ciò avviene la variabile locale nasconderà quella globale.

In generale è opportuno ridurre al minimo l'uso di riferimenti "globali", è meglio passare la variabile come argomento e quindi riportare indietro la variabile modificata.

Il secondo caso, quando si fa riferimento ad un nome che non si trova nello spazio locale corrente, viene risolto come segue: la funzione ricerca il nome all'interno del proprio spazio locale, se non lo trova lo cerca nello spazio del modulo ed infine se ancora non lo trova lo cerca nello spazio "builtin". L'unico problema con questo meccanismo si ha quando si vuole assegnare un valore ad una variabile esterna. Di regola questo provocherebbe la creazione di un nuovo nome di variabile, che non è ciò che vogliamo. Allora dovremo specificare la variabile come globale per evitare che venga creata una versione locale del nome.

Vediamo tutto ciò con un esempio (che ha il solo scopo di illustrare questo punto):

# variabili nello spazio dei nomi del modulo
W = 5
Y = 3
 
#gli argomenti si comportano come variabili della funzione
#quindi X è nello spazio locale
def spam(X):
    
   #indica alla funzione di riferirsi allo spazio 
   #del modulo senza creare un proprio nome W
   global W
   
   Z = X*2 # la nuova variabile Z viene creata nello spazio locale
   W = X+5 # usa la W dello spazio del modulo

   if Z > W:
      # print è un nome dello spazio "builtin"
      print "2 x X is greater than X + 5"
      return Z
   else:
      return Y # non esiste una Y locale, quindi si usa quella del modulo

Quando si importa un modulo come sys il nome sys diventa disponibile nello spazio locale e quindi possiamo accedere ai nomi contenuti nello spazio del modulo sys specificando i nomi come abbiamo già visto. Se invece usiamo:

from sys import exit

È solo il nome exit che viene trasportato nello spazio locale. In tal caso non possiamo usare nessun altro nome definito in sys, nemmeno lo stesso sys .

E quello del BASIC

Il BASIC utilizza un approccio opposto a Python considerando tutte le variabili globali per definizione (per compatibilità con vecchie versioni di BASIC), ma consentendo al programmatore di creare variabili LOCAL all'interno delle funzioni.

Tcl

In Tcl non sembra esserci alcun controllo sugli spazi dei nomi. Probabilmente a causa del modo singolare usato da Tcl per analizzare il programma. In ogni caso sembra che tutte le variabili siano locali rispetto al loro ambiente circostante: variabili a livello di file sono visibili solo a comandi contenuti nel file e variabili a livello di procedura sono accessibili solo all'interno della procedura. Per comunicare valori fra i due spazi dei nomi occorre passarli come argomenti.


Precedente  Successivo  Indice;


Se avete domande o suggerimenti relativi a questa pagina mandate un e-mail all'autore: alan.gauld@yahoo.co.uk o al traduttore italiano: lfini@arcetri.astro.it