
Il metodo __repr__ in Python
Oggi parliamo del metodo `__repr__` in Python. Questo metodo ti permette di definire come un oggetto viene rappresentato quando viene chiamato tramite la funzione repr().
__repr__
È usato soprattutto nel debugging per avere una rappresentazione stringa chiara e informativa degli oggetti.
Quando viene chiamato ritorna una stringa che rappresenta l'oggetto.
In genere l'obiettivo di `__repr__` è fornire una stringa che, idealmente, potrebbe essere utilizzata per ricreare l'oggetto stesso. In altre parole, se si copia e incolla l'output di `__repr__` nel codice Python, dovrebbe creare un oggetto identico.
Vediamo un esempio pratico.
Supponi di avere una classe `Persona`.
class Persona:
def __init__(self, nome, eta):
self.nome = nome
self.eta = eta
def __repr__(self):
return f"Persona(nome='{self.nome}', eta={self.eta})"
In questa classe è implementato il metodo `__repr__` per restituire una stringa che mostra il nome della classe e i valori degli attributi dell'istanza.
Crea un'istanza della classe
studente = Persona('Alice', 30)
Ora accedi al contenuto dell'oggetto tramite la funzione repr()
print(repr(studente))
L'output sarà una stringa:
Persona(nome='Alice', eta=30)
Come puoi vedere, l'output è chiaro e informativo. Ora sai che l'oggetto è un'istanza della classe `Persona` con il nome 'Alice' e l'età 30.
Facciamo un altro esempio più complesso.
Definisci una classe `Libro` implementando il metodo __repr__.
class Libro:
def __init__(self, titolo, autore, pagine):
self.titolo = titolo
self.autore = autore
self.pagine = pagine
def __repr__(self):
return (f"Libro(titolo='{self.titolo}', autore='{self.autore}', "
f"pagine={self.pagine})")
Ora crea un'istanza di `Libro`
libro = Libro('Il Piacere di Scoprire', 'Richard Feynman', 320)
Infine accedi al metodo `__repr__` tramite la funzione repr().
print(repr(libro))
Libro(titolo='Il Piacere di Scoprire', autore='Richard Feynman', pagine=320)
Il metodo ti mostra tutte le informazioni che gli hai chiesto di visualizzare.
Generalmente, gli sviluppatori cercano di fare in modo che l'output di `__repr__` possa essere copiato e incollato nel codice per creare un nuovo oggetto. Quindi, è molto importante che l'output sia chiaro, utile e completo, deve includere tutte le informazioni necessarie per ricreare l'oggetto.
Come avrai già notato, questo metodo compie lo stesso lavoro del metodo __str__.
Quindi, è normale chiedersi quale sia la differenza tra questi due metodi. Proviamo a rispondere a questa domanda nel paragrafo seguente.
La differenza tra i metodi __repr__ e __str__
Questi due metodi servono a rappresentare un oggetto come stringa, ma hanno scopi leggermente diversi.
- Il metodo __repr__
Viene richiamato dalla funzione repr() ed è usato principalmente dagli sviluppatori. Idealmente, dovrebbe essere una stringa che, se passata a eval(), ricrea l'oggetto. - Il metodo __str__
Viene richiamato dalle funzioni print() e str(). È principalmente destinato agli utenti finali. Restituisce una stringa che descrive l'oggetto in modo leggibile.
Quindi, le principali differenze tra i metodi sono le funzioni utilizzate per eseguirli e lo scopo finale.
Cerchiamo di capire meglio come funzionano questi due metodi con un esempio pratico.
Definisci la classe `Persona` implementando entrambi i metodi.
class Persona:
def __init__(self, nome, eta):
self.nome = nome
self.eta = eta
def __repr__(self):
return f"Persona(nome='{self.nome}', eta={self.eta})"
def __str__(self):
return f"{self.nome}, {self.eta} anni"
Ora crea un'istanza di `Persona`.
studente = Persona('Alice', 30)
Quando utilizzi la funzione repr() sull'oggetto 'studente' Python chiama il metodo __repr__
print(repr(studente))
Persona(nome='Alice', eta=30)
Viceversa, quando usi la funzione print() sullo stesso oggetto, Python chiama il metodo __str__
print(studente)
Alice, 30 anni
Lo stesso accade quando utilizziamo la funzione str().
print(str(studente))
Alice, 30 anni
In conclusione, la differenza tra i due metodi è soprattutto l'obiettivo finale.
Nel caso del metodo __repr__ la stringa è una rappresentazione utile per il debugging, mentre nel caso del metodo __str__ è una rappresentazione leggibile e user-friendly destinata agli utenti finali.
Fall-Back Mechanism. Se una classe ha solo `__repr__` implementato, `str()` userà `__repr__` come fallback. Il risultato in uscita è sempre lo stesso. Tuttavia, è una buona pratica di programmazione definire entrambi se i loro scopi differiscono.
class Persona:
def __init__(self, nome, eta):
self.nome = nome
self.eta = eta
def __repr__(self):
return f"Persona(nome='{self.nome}', eta={self.eta})"
Crea un'istanza della classe
studente = Persona('Alice', 30)
Ora prova ad accedere al contenuto dell'oggetto tramite la funzione str()
print(str(studente))
Persona(nome='Alice', eta=30)
In questo caso Python chiama automaticamente il metodo __repr_ perché il metodo __str__ non è definito nella classe.
Pertanto, puoi anche decidere di utilizzare solo uno dei due metodi.
E' però consigliato implementare entrambi correttamente per migliorare la chiarezza e l'usabilità del codice.
Spero che ora le differenze siano più chiare!