lettura facile

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!




Se qualcosa non ti è chiaro, scrivi la tua domanda nei commenti.




FacebookTwitterLinkedinLinkedin