2016-04-20 15 views
8

Co chcę zrobić, to stworzyć klasę, która otacza int i pozwala na pewne rzeczy, które normalnie nie są dozwolone w typach int. Nie obchodzi mnie, czy to nie jest pythonic czy w/e, tylko szukam wyników. Oto mój kod:Automatyczne konwersje typów zdefiniowanych przez użytkownika klas

class tInt(int): 
    def __add__(self, other): 
     if type(other) == str: 
      return str(self) + str(other) 
     elif type(other) == int: 
      return int(self) + other 
     elif type(other) == float: 
      return float(self) + float(other) 
     else: 
      return self + other 
a = tInt(2) 
print (a + "5") 
print ("5" + a) 

Dane wyjściowe.

>> 25 
Traceback (most recent call last): 
    File "C:\example.py", line 14, in <module> 
    print ("5" + a) 
TypeError: Can't convert 'tInt' object to str implicitly 

Tak więc pierwsza instrukcja drukowania przebiegła ładnie i dała to, czego się spodziewałem, ale druga dała błąd. Myślę, że to dlatego, że pierwszy używa funkcji tInt's add, ponieważ pojawił się przed + "5", a drugi po raz pierwszy użył funkcji "5" w postaci dodaj ponieważ pojawił się pierwszy. Wiem o tym, ale nie wiem, jak wymusić funkcję dodać lub pozwolić klasa tInt być reprezentowana jako ciąg/int/etc .., gdy normalny typ pojawia się przed nim w operacji.

+4

Klauzula "else" spowoduje nieskończoną rekursję. 'self + other' wywoła' self .__ dodaj __ (inne) 'ponownie. – chepner

+0

Cholera, nie myślałem o tym. Powinienem więc "oczyścić" wszystkie moje pozostałe, upewniając się, że jaźń jest innego rodzaju? – tatatat0

+2

Zamiast tego należy użyć 'return NotImplemented'. Spowoduje to, że Python wypróbuje 'tInt .__ radd __ (other)' ifto jest zdefiniowany lub wypróbuje 'type (other) .__ add __ (self)' if not. – chepner

Odpowiedz

13

Musisz zaimplementować metodę __radd__, aby obsłużyć przypadek, gdy instancja klasy znajduje się po prawej stronie dodania.

docs powiedzieć:

Metody te nazywane są w celu realizacji operacji arytmetycznych binarny (+, -, *, @ /, //,%, divmod(), pow() * *, < <, >>, &, ^, |) z odzwierciedlonymi (zamienionymi) operandami. Funkcje te są wywoływane tylko wtedy, gdy lewy operand nie obsługuje odpowiadającej operacji, a operandy są różnych typów. 2 Na przykład, aby ocenić wyrażenie X-Y , gdzie y jest instancją klasy, która ma metodę rsub(), y. rsub (x) jest wywoływane, jeśli x. sub (y) zwraca niezatwierdzony.

Przykład:

class tInt(int): 

    def __add__(self, other): 
     if isinstance(other, str): 
      return str(self) + str(other) 
     elif isinstance(other, int): 
      return int(self) + other 
     elif isinstance(other, float): 
      return float(self) + float(other) 
     else: 
      return NotImplemented 

    def __radd__(self, other): 
     return self.__add__(other) 

a = tInt(2) 
for x in ["5", 5, 5.0]: 
    print (a + x) 
    print (x + a) 

25 
25 

7 
7 

7.0 
7.0 

Jak @chepner zauważył w komentarzach, wracając NotImplemented przypadków, że metoda nie obsługuje spowoduje Python spróbować innych sposobów wykonywania operacji, albo podnieść TypeError, jeśli nie ma możliwości wykonania żądanej operacji.

Powiązane problemy