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 :
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?
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%