Warum verwendet Fraction __new__ anstelle von __init__?

8

Ich versuche einen neuen unveränderlichen Typ zu erstellen, der dem eingebauten Fraction ähnelt, aber nicht von ihm abgeleitet ist. Die Fraktionsklasse wird so erstellt :

%Vor%

aber ich sehe nicht, wie sich das von

unterscheidet %Vor%

Das Erstellen von 2 Fraction -Objekten mit demselben Wert erstellt keine 2 Beschriftungen, die auf dasselbe Objekt / denselben Speicherort zeigen. (Tatsächlich wurde in den Kommentaren darauf hingewiesen, dass Typen nicht üblich sind Mach das.)

Trotz des Quellcode-Kommentars sind sie nicht wirklich unveränderlich:

%Vor%

Also, was ist der Zweck, es so zu machen?

Die Dokumentation sagt

  

__new__() soll vor allem Unterklassen von unveränderlichen Typen (wie int, str oder tuple) erlauben, die Instanzerstellung anzupassen. Es ist auch   häufig in benutzerdefinierten Metaklassen überschrieben, um die Klasse anzupassen   Schöpfung.

Wenn ich also keinen eingebauten Typ herlege, sondern einen unveränderlichen Typ von Grund auf neu schaffe (Unterklasse von object ), muss ich ihn dann noch benutzen?

    
endolith 17.09.2014, 23:24
quelle

1 Antwort

4

Wenn Sie einen wirklich unveränderlichen Typ erstellen, sollten Sie __new__ verwenden, da das self -Objekt, das in __init__ übergeben wurde, bereits logisch unveränderlich wäre. Daher wäre es zu spät, das Objekt zuzuweisen Werte für seine Mitglieder. Dies ist für diejenigen, die Unterklassen schreiben, drastischer, weil das Hinzufügen von Mitgliedern verboten wäre.

Da Unveränderbarkeit eigentlich keine intrinsische Eigenschaft ist, sondern ein Trick, der generell durch das Hooking von __setattr__ erzwungen wird, schreiben Leute unveränderliche Typen, die mit __init__ initialisieren und dann make selbst unveränderlich machen, indem sie einige setzen Mitglied, das dann die Einstellung anderer Mitglieder unmöglich macht. Aber die Logik in solchen Situationen kann ziemlich gewunden werden und __setattr__ kann mit zusätzlichen Regeln durchsetzt werden.

Es macht mehr Sinn, eine Art veränderbaren Typ zu haben und den unveränderlichen Typ von ihm mit der Version von __setattr__ zu erben, die nur eine Ausnahme in der Unterklasse erhöht. Dies macht die Logik der Verwendung von __new__ offensichtlich. Da es die veränderbare Oberklasse erstellen und ändern kann, sie aber dann als geerbten Typ zurückgibt, ist sie weniger verwirrend.

Wenn Fraktion unveränderlich sein sollte, haben die Implementierer diesen Schritt entweder verpasst oder später darüber nachgedacht und vergessen, ihren Kommentar zu entfernen.

%Vor%     
Jon Jay Obermark 19.09.2014 22:13
quelle

Tags und Links