2016-05-18 5 views
4

Mit V3 von Python erwarten, ich erstellen:Python: rtruediv nicht funktioniert, wie ich

class NewInt(int): 
    def __rtruediv__(self, num): 
    print('in here') 

x = NewInt(5) 

343/x # called rtruediv as I expect, but 

343.3/x # does not call rtruediv 

nicht sicher, warum dies ist, weil:

x/343 
x/343.3 #both will call truediv 

Für mich ist diese inkonsistent scheint ..

Jeder hat eine Erklärung, warum das ist .. und wenn Python 343.3/x gibt es eine Methode, die überschrieben werden kann?

Ich fand dieses Verhalten bei der Überprüfung einiger Informationen über das Überladen und stieß auf diese Inkonsistenz.

Dave

Antwort

3

__rtruediv__ hat nur Vorrang vor __truediv__, wenn der rechte Operand eine Instanz einer Unterklasse der linken Operanden-Klasse ist.

Wenn Sie tun 343/x, NewInt ist eine Unterklasse von int, so x __rtruediv__ bekommt Priorität. Wenn Sie 343.3/x tun, ist NewInt keine Unterklasse von float, so dass 343.3 __truediv__ Priorität erhält.

343.3.__truediv__(x) gibt NotImplemented nicht zurück, da float weiß, wie man einen Float durch einen Int. Daher wird x.__rtruediv__ nicht aufgerufen.

3

Kurz gesagt, der linke Operand erhält die erste Einstellung für die Operation, außer unter besonderen Umständen.

Die entsprechende Dokumentation ist hier in emulating numeric types:

Hinweis: Wenn der Typ des rechten Operanden eine Unterklasse des linken Operanden-Typs ist und dass Unterklasse bietet das reflektierte Verfahren für den Betrieb, wird diese Methode vor aufgerufen werden die nicht reflektierte Methode des linken Operanden. Mit diesem Verhalten können Unterklassen die Operationen ihrer Vorfahren überschreiben.

So im Fall von:

343.3/x # does not call rtruediv 

Die linke Hand gewinnt, weil float Division durch int definiert ist, und NewIntis a n int. Das heißt, 343.3.__truediv__(x) ist ohne Fehler erfolgreich.

Lasst uns alle vier Fälle im Lichte der Dokumentation Einklang zu bringen, um zu sehen, dass es hier nicht wirklich inkonsistentes Verhalten ist:

343/x  # x.__rtruediv__ wins because NewInt subclasses int 
343.3/x # 343.3.__truediv__ wins because NewInt doesn't subclass float 
x/343  # x.__truediv__ wins because int doesn't subclass NewInt 
x/343.3 # x.__truediv__ wins because float doesn't subclass NewInt 
+0

ahh .. sowohl dieses als auch die eine große Antworten unten sind. Ich hatte keine Ahnung von den tatsächlichen Details, wie Python Objekte auf der rechten Seite eines Operators behandelt. Es ist nicht ganz so, wie ich es erwartet habe, und ich kann jetzt sehen, dass es so sein muss. Es gibt also tatsächlich keine Möglichkeit, die Operation von: 343.3/x mit einer neuen Methode in NewInt zu übersteuern, weil sie die truediv-Methode des float-Objekts verwendet. Das Überfahren von Bedienern wird komplexer, als man zunächst annehmen könnte. Einige Texte scheinen dieses "Detail" auszulassen – Dave

+0

Das ist nicht ganz richtig.Es ist möglich, wenn 'NewInt' geändert wird, um' int' nicht zu erben (oder irgendeine andere Klasse, für die das Floaten weiß, wie man teilt). In diesem Fall wird der Versuch auf der linken Seite fehlschlagen, aber die rechte Seite erhält jetzt einen Schuss. Wenn Sie dann "__truediv__" korrekt implementiert haben, wird das Ergebnis der Divisionsmethode des rechten Operanden ohne Fehler zurückgegeben. – wim