Come passare un valore per riferimento in Python

di Lorenzo Neri
20 visualizzazioni

Come passare un valore per riferimento in Python? Esiste un modo per gestire i valori “by reference”? Scoprilo assieme a me in questo articolo!

In Python, a differenza di quanto accade in altri linguaggi come PHP oppure C#, se volessi passare un valore per riferimento non hai a tua disposizione degli operatori ben specifici.

Non solo: la documentazione di Python con l’esempio fornito, non sembra troppo convincente.

Per intenderci:

class PassaPerReference:
    def __init__(self):
        self.variabile = 'Originale'
        self.cambia(self.variabile)
        print(self.variabile)

    def cambia(self, var):
        var = 'Cambiato'

Eppure sembra che il valore non cambi affatto: che fare allora?

Passare per riferimento: ragioniamo in due passi

In Python abbiamo a che fare con due fattori da prendere in considerazione in questo caso.

  1. Il parametro che stiamo passando è attualmente la referenza ad un oggetto, ma se ci fai caso nell’esempio di prima è passata per valore.
  2. Alcuni tipi di dato sono mutabili ma altri no.

Che significa ciò che ho appena scritto? Beh diciamo che in sintesi significa appunto prendere in considerazione due aspetti.

Se stai cercando di passare un oggetto mutabile all’interno di un metodo, il metodo stesso ottiene il riferimento allo stesso oggetto. Quindi, puoi certamente mutarlo, ma lo scope esterno non ne è a conoscenza: che significa? Che la referenza esterna al metodo sta puntando all’oggetto originale.

In sintesi: non è il modo corretto di passare un valore per riferimento in Python.

Dobbiamo però parlare degli oggetti immutabili. Se ripetiamo il processo che ti ho appena esposto, non cambia nulla, eccezion fatta che l’oggetto stesso non potrà nemmeno essere mutato.

Ciò detto, cerchiamo di capire come passare un valore per riferimento, ma seguendo le due tipologie di oggetti che abbiamo in Python.

Passare un valore per riferimento: tipi mutabili

Usiamo nel nostro esempio una lista, quindi eseguiremo il processo “pass by reference” di un mutable.

Facciamo l’esempio a seguire:

def provo_a_cambiare_i_contenuti_della_lista(la_lista):
    print('ottengo', la_lista)
    la_lista.append('quattro')
    print('modificato in', la_lista)

lista_esterna = ['uno', 'due', 'tre']

print('prima, lista_esterna =', lista_esterna)
provo_a_cambiare_i_contenuti_della_lista(lista_esterna)
print('dopo, lista_esterna =', lista_esterna)

Abbastanza lineare e pratico no? Ecco, questo è l’output:

prima, lista_esterna = ['uno', 'due', 'tre']
ottengo ['uno', 'due', 'tre']
modificato in ['uno', 'due', 'tre', 'quattro']
dopo, lista_esterna = ['uno', 'due', 'tre', 'quattro']

Per fartela breve, ciò che succede è che il parametro è passato per riferimento tramite “lista_esterna” e NON con una sua copia.

Siccome stiamo usando un mutable otteniamo il nostro scopo e le modifiche ottenute grazie al “pass by reference” si mantengono anche nello scope esterno al metodo!

Ora, vediamo come possiamo passare per riferimento nel secondo caso.

Passare un valore per riferimento: tipi immutabili

In questo caso ripetiamo il cinema del “pass by reference” di un immutable. Con chi? Con una stringa.

Proviamoci con il seguente esempio:

def provo_a_cambiare_la_stringa_per_referenza(la_stringa):
    print('ottengo', la_stringa)
    la_stringa = 'Sto cercando di fare riferimento...'
    print('modifico in', la_stringa)

stringa_esterna = 'Stavo cercando di fare riferimento'

print('prima, stringa_esterna =', stringa_esterna)
provo_a_cambiare_la_stringa_per_referenza(stringa_esterna)
print('dopo, stringa_esterna =', stringa_esterna)

Guarda un po’ cosa succede:

prima, stringa_esterna = Stavo cercando di fare riferimento
ottengo Stavo cercando di fare riferimento
modifico in Sto cercando di fare riferimento...
dopo, stringa_esterna = Stavo cercando di fare riferimento

Il parametro “la_stringa” è passato per valore e di fatto le modifiche NON si mantengono nello scope esterno.

In questo caso, ciò che avviene è una vera e propria generazione di una copia e di fatto non abbiamo alcuna modifica concreta al di fuori del metodo stesso.

Potrebbero interessarti

Lascia un commento

Questo sito potrebbe fare uso di cookie e siccome l'UE mi obbliga a fartelo presente, eccoti il classico banner dove puoi decidere come gestirli. Accetta Leggi di più