2015-08-05 12 views
6

Próbuję nauczyć się Pythona własnymi i utknąłem w funkcji __repr__. Chociaż przeczytałem wiele post na __repr__ wraz z dokumentem Pythona. więc postanowiłem zadać to pytanie tutaj. Kod poniżej wyjaśnia moje zamieszanie.jakie jest znaczenie funkcji "__repr__" w stosunku do normalnej funkcji

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) 

Jeśli normalną funkcję można również wykonać podobne zadanie to co jest dodatkową zaletą __repr__ nad print_class() (w moim przypadku to normalna funkcja) funkcja.

Odpowiedz

5

Funkcja __repr__ jest wywoływana wewnętrznie przez repr(). repr() jest wywoływana podczas bezpośredniego drukowania obiektu, a klasa nie definiuje wartości __str__(). Od documentation -

obiekt .__ __ repr (self)

Wywoływana przez repr() funkcja wbudowana i konwersji ciągów (reverse cytaty), aby obliczyć „oficjalne” ciąg znaków reprezentujący obiekt. Jeśli to w ogóle możliwe, powinno to wyglądać jak poprawne wyrażenie w języku Python, które może być użyte do odtworzenia obiektu o tej samej wartości (w odpowiednim środowisku). Jeśli nie jest to możliwe, należy zwrócić ciąg znaków w postaci < ... jakiś użyteczny opis ...>. Wartość zwracana musi być obiektem typu string. Jeśli klasa definiuje __repr__(), ale nie __str__(), wówczas __repr__() jest również używana, gdy wymagana jest "nieformalna" reprezentacja łańcuchów wystąpień tej klasy.

W twoim przypadku dla print_class(), musisz wyraźnie wywołać metodę podczas drukowania obiektu. Ale w przypadku __repr__(), zostaje wewnętrznie wywołana przez print.

Jest to szczególnie przydatne w przypadku miksowania różnych klas/typów.Na przykład pozwala nam wybrać listę, która może zawierać liczby i obiekty klasy point, a teraz chcesz wydrukować elementy listy.

Jeśli nie definiują __repr__() lub __str__(), trzeba by najpierw sprawdzić instancji, czy jego typu Point jeśli tak nazywają print_class(), lub jeśli nie bezpośrednio drukować numer.

Ale gdy klasa definiuje __repr__() lub __str__(), można po prostu bezpośrednio zadzwonić print wszystkich elementów listy, print stwierdzenie byłoby wewnętrznie dbać o drukowaniu poprawne wartości.

przykład, pozwala zakładać, klasę, która ma print_class() metodę, ale nie __repr__() lub __str__(), kod -

>>> 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 

Jak widać, gdy zmieszamy numery i obiektów typu CA na liście, a następnie kiedy właśnie zrobiliśmy print(i), nie wydrukowaliśmy tego, co chcieliśmy. Aby to działało poprawnie, musieliśmy sprawdzić typ i i wywołać odpowiednią metodę (jak to zrobiono w drugim przypadku).

Teraz pozwala zakładać klasę implementującą __repr__() zamiast 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 

Jak widać w drugim przypadku, po prostu drukowanie działało, ponieważ print wewnętrznie wywołuje __str__() pierwszy, a jako że nie istnieją opadł do __repr__().

I nie tylko to, gdy wykonujemy str(list), wewnętrznie wywoływana jest każda pozycja elementu listy __repr__(). Przykład -

pierwszym przypadku (bez __repr__()) -

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

drugim przypadku (z __repr__()) -

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

Również w interaktywny interpreter, jeśli są bezpośrednio przy użyciu obiektu , pokazuje wynik działania funkcji repr(), Przykład -

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

Czy możesz wyjaśnić swój 3, 4 i 5 (mieszanie różnych klas/typów -) komentarz z kodem przykładowym. Dziękuję za wszystkie wyjaśnienia. – jax

+0

OK, pozwól mi zaktualizować. –

+0

Zaktualizowano odpowiedź, podając szczegółowe przykłady. –

3

Różnica polega na tym, że funkcja __repr__ jest automatycznie wywoływana przez język Python w niektórych kontekstach i jest częścią wstępnie zdefiniowanego interfejsu API z określonymi wymaganiami. Na przykład, jeśli wpiszesz w powłoce interaktywnej p (nie print p) po utworzeniu obiektu p, zostanie wywołana jego __repr__. Będzie również używany dla print p, jeśli nie zdefiniujesz __str__ na p. (Oznacza to, że trzeba było napisać print p.print_class(), ale nie trzeba pisać print p.__repr__(); Python o nazwie __repr__ automatycznie.) Wymagania dotyczące __repr__ są opisane w the documentation:

Wywoływana przez repr() wbudowane -in konwersji funkcji i łańcuchów znaków (cudzysłowy odwrotne) w celu obliczenia "oficjalnej" reprezentacji łańcuchowej obiektu. Jeśli to w ogóle możliwe, powinno to wyglądać jak poprawne wyrażenie w języku Python, które może być użyte do odtworzenia obiektu o tej samej wartości (w odpowiednim środowisku). Jeśli nie jest to możliwe, należy zwrócić ciąg znaków w postaci < ... jakiś użyteczny opis ...>.

W skrócie, jeśli napiszesz swoją własną metodę zwaną print_class można je robić co chcesz i powiedzieć ludziom, jak go używać, ponieważ to twoja API. Jeśli używasz __repr__, powinieneś postępować zgodnie z konwencjami API Pythona. Każdy może mieć sens w zależności od kontekstu.

+0

@BrenBam Oznacza to, że mogę napisać funkcję lub metodę równoważną __repr__, jeśli nie chcę jej użyć lub istnieje jakieś zadanie, które nie może być wykonane/przyjąć bez funkcji __repr__. – jax

+0

dzięki za wyjaśnienie – jax

+0

@jax: Możesz napisać własną metodę, tak. – BrenBarn

0

Pomaga w bardziej wydajnym kodowaniu. pomimo tego, że uzyskujesz ten sam wynik przy użyciu metody definiowania przez użytkownika, np. 'print_class()' jako repr, ale nie musisz wpisywać metody '.print_class()' metodą repr.

Powiązane problemy