2015-08-05 9 views
6

Sto cercando di imparare Python con il mio e ho bloccato la funzione __repr__. Anche se ho letto un sacco di post su __repr__ insieme al documento python. quindi ho deciso di fare questa domanda qui. Il codice qui sotto spiega la mia confusione.qual è il significato della funzione `__repr__` rispetto alla normale funzione

class Point: 

    def __init__(self,x,y): 
      self.x, self.y = x,y 

    def __repr__(self): 
     return 'Point(x=%s, y=%s)'%(self.x, self.y) 

    def print_class(self): 
     return 'Point(x=%s, y=%s)'%(self.x, self.y) 



p = Point(1,2) 

print p 
print p.print_class() 


Point(x=1, y=2) 
Point(x=1, y=2) 

Se una funzione normale può anche svolgere funzioni simili allora qual è il vantaggio supplementare di __repr__ sopra print_class() (nel mio caso una normale funzione) Funzione.

risposta

5

La funzione __repr__ è chiamata da repr() internamente. repr() viene chiamato quando si stampa direttamente l'oggetto e la classe non definisce uno __str__(). Da documentation -

oggetto .__ repr __ (self)

Chiamato dal repr() funzione built-in e da conversioni di stringhe (apici inversi) per calcolare la rappresentazione “ufficiale” stringa di un oggetto. Se possibile, dovrebbe apparire come un'espressione Python valida che potrebbe essere utilizzata per ricreare un oggetto con lo stesso valore (dato un ambiente appropriato). Se ciò non è possibile, deve essere restituita una stringa del modulo < ... qualche descrizione utile ...>. Il valore restituito deve essere un oggetto stringa. Se una classe definisce __repr__() ma non __str__(), allora viene utilizzato anche __repr__() quando è richiesta una rappresentazione di stringa "informale" di istanze di tale classe.

Nel proprio caso per print_class(), è necessario chiamare in modo specifico il metodo quando si stampa l'oggetto. Ma in caso di __repr__(), viene internamente chiamato da print.

Ciò è particolarmente utile quando si mescolano classi/tipi diversi.Per esempio, prendi una lista che può avere numeri e oggetti della tua classe point, ora vuoi stampare gli elementi della lista.

Se non definire il __repr__() o __str__(), si dovrebbe verificare prima l'istanza, se il suo tipo di Point se così chiamata print_class(), o se non stampare direttamente il numero.

Ma quando la classe definisce il __repr__() o __str__(), si può chiamare direttamente print su tutti gli elementi della lista, print affermazione sarebbe ingerire cura di stampare i valori corretti.

esempio, consente di assumere una classe che ha print_class() metodo, ma nessun __repr__() o __str__(), codice -

>>> class CA: 
...  def __init__(self,x): 
...    self.x = x 
...  def print_class(self): 
...    return self.x 
... 
>>> l = [1,2,3,CA(4),CA(5)] 
>>> for i in l: 
...  print(i) 
... 
1 
2 
3 
<__main__.CA object at 0x00590F10> 
<__main__.CA object at 0x005A5070> 
SyntaxError: invalid syntax 
>>> for i in l: 
...  if isinstance(i, CA): 
...    print(i.print_class()) 
...  else: 
...    print(i) 
... 
1 
2 
3 
4 
5 

Come si può vedere, quando mescoliamo i numeri e oggetti di tipo CA nella lista, e poi quando abbiamo appena fatto print(i), non ha stampato ciò che volevamo. Affinché questo funzioni correttamente, abbiamo dovuto verificare il tipo di i e chiamare il metodo appropriato (come fatto nel secondo caso).

Ora lascia supporre una classe che implementa __repr__() invece di print_class() -

>>> class CA: 
...  def __init__(self,x): 
...    self.x = x 
...  def __repr__(self): 
...    return str(self.x) 
... 
>>> 
>>> l = [1,2,3,CA(4),CA(5)] 
>>> for i in l: 
...  print(i) 
... 
1 
2 
3 
4 
5 

Come si può vedere nel secondo caso, è sufficiente la stampa ha lavorato, dal momento che print chiama internamente __str__() prima, e come che non esisteva ricadde a __repr__().

E non solo, quando facciamo str(list), internamente viene chiamato l'elemento __repr__() di ogni elemento dell'elenco. Esempio -

primo caso (senza __repr__()) -

>>> str(l) 
'[1, 2, 3, <__main__.CA object at 0x005AB3D0>, <__main__.CA object at 0x005AB410>]' 

secondo caso (con __repr__()) -

>>> str(l) 
'[1, 2, 3, 4, 5]' 

Inoltre interprete interattivo, quando si sta utilizzando direttamente l'oggetto , ti mostra l'output della funzione repr(), Esempio -

>>> class CA: 
...  def __repr__(self): 
...    return "CA instance" 
... 
>>> 
>>> c = CA() 
>>> c 
CA instance 
+0

Puoi spiegare i tuoi commenti 3, 4 e 5 (mescolando classi/tipi diversi) con il codice di esempio. Grazie per tutte le tue spiegazioni – jax

+0

Ok sicuro, fammi aggiornarlo. –

+0

Aggiornamento della risposta con esempi dettagliati. –

3

La differenza è che la funzione __repr__ viene chiamata automaticamente da Python in determinati contesti e fa parte di un'API predefinita con requisiti specifici. Ad esempio, se inserisci p da solo (non print p) nella shell interattiva dopo aver creato l'oggetto p, verrà chiamato il suo __repr__. Verrà inoltre utilizzato per print p se non si definisce __str__ su p. (Cioè, si dovuto scrivere print p.print_class(), ma non c'era bisogno di scrivere print p.__repr__(); Python chiamato __repr__ automaticamente per voi.) I requisiti per __repr__ sono descritti in the documentation:

Chiamato dal repr() costruito -in funzione e mediante conversioni di stringhe (virgolette) per calcolare la rappresentazione stringa "ufficiale" di un oggetto. Se possibile, dovrebbe apparire come un'espressione Python valida che potrebbe essere utilizzata per ricreare un oggetto con lo stesso valore (dato un ambiente appropriato). Se ciò non è possibile, deve essere restituita una stringa del modulo < ... qualche descrizione utile ...>.

In breve, se si scrive il proprio metodo chiamato print_class si può fargli fare quello che vuoi e dire alla gente come usarlo, perché è il tuo API. Se usi __repr__ devi seguire le convenzioni dell'API di Python. O si può avere un senso a seconda del contesto.

+0

@BrenBam Quindi significa che posso scrivere una funzione o un metodo equivalente a __repr__ se non desidero usarlo o c'è un compito che non può essere eseguito/presupposto senza la funzione __repr__. – jax

+0

grazie per aver spiegato – jax

+0

@jax: puoi scrivere il tuo metodo, sì. – BrenBarn

0

Ti aiuta a fare lavori di codifica più efficienti. anche se ottieni lo stesso risultato utilizzando il metodo di definizione utente come "print_class()" come repr, ma non è necessario digitare ".print_class()" con il metodo repr.

Problemi correlati