Ich schreibe Mathematik -Dienstprogrammklassen ListVector und tupleVector ,
Erben aus der Liste bzw. Tuple :
Code: Select all
class ListVector(list):
...
class TupleVector(tuple):
...
< /code>
(Abgesehen davon: Ich behaupte nicht unbedingt, dass dies wirklich eine gute Idee ist; in der Tat,
bin ich mir bewusst, dass ich dies wohl nicht tun sollte, da meine beabsichtigten Beziehungen logisch "has-a"-"-"-"-als" is-a ",
und unangemessenes Basspflichten, das von dem Basis-AS-AS-AS-AS-AS-AS-AS-AS-AS-AS-AS-AS-AS-ASS-ASS-ASS-ASS-ASS-ASS-ASS-ASS-ASS-ASS-ASS, ist, wenn es nicht gefährlich ist, wenn es nicht gefährlich ist. Meine
Klassen, z. /> [url=viewtopic.php?t=14917]Ich möchte[/url] den Vergleich von ListVector < /code> gegen TupleVector < /code> verwenden. Ich möchte, dass dies erfolgreich ist: < /p>
assert ListVector((1,2,3)) == TupleVector((1,2,3))
< /code>
Beachten Sie, dass sich dies vom Verhalten der Basisklasse unterscheidet: < /p>
assert list((1,2,3)) != tuple((1,2,3))
< /code>
i.e.
assert [1,2,3] != (1,2,3)
Aber ich habe zunächst vergessen, sie in meinem ListVector < /code> Klasse zu implementieren.
Code: Select all
assert ListVector((1,2,3)) == TupleVector((1,2,3)) # unexpectedly succeeds!
und so dass der Assprüger fehlschlägt. Verhalten: Aufrufe reflektierter TupleVector .__ EQ __ Stattdessen,
, was true zurückgibt, und so ist die Behauptung erfolgreich! LIST .__ EQ __ < /code>? < /p>
Nach den hier beschriebenen Regeln
(was aus dieser FAQ entnommen wird),
Ich denke, es sollte die Liste nennen .__ EQ __ < /code>. überschrieben __eq __ (dh type (a) .__ EQ __ ist kein Objekt .__ EQ __ ), dann ist das Ergebnis a .__ EQ __ (b) . /> < /blockquote>
Mein Lesen der Dokumentation scheint auch zu der gleichen Schlussfolgerung zu führen wie die FAQ (dh die Methode des linken Operanden, d. H. List .__ Gl. __ < /code>, sollte aufgerufen werden): < /p>
Wenn der Operand den Operand der Operand der Operands von der richtigen Art und Oper von unterschiedlichem Operand ist, ist der Typ. Typ, die reflektierte Methode des rechten Operand
Code: Select all
#!/usr/bin/python3
class ListVector(list):
# OOPS! Forgot to implement __eq__ and __ne__ for ListVector
# ...
pass
class TupleVector(tuple):
def __eq__(self, other):
print("TupleVector.__eq__ called")
# strict=True so comparing Vectors of unequal length will throw
return all(x==y for x,y in zip(self,other, strict=True))
def __ne__(self, other):
return not self.__eq__(other)
# ...
# Unit test
assert repr(ListVector((1,2,3))) == "[1, 2, 3]" # succeeds as expected
assert repr(TupleVector((1,2,3))) == "(1, 2, 3)" # succeeds as expected
assert TupleVector((1,2,3)) == ListVector((1,2,3)) # emits "TupleVector.__eq__ called" and succeeds, as expected
assert ListVector((1,2,3)) == TupleVector((1,2,3)) # WTF: unexpectedly emits "TupleVector.__eq__ called" and succeeds!
# Confirm that the condition "type(a).__eq__ isn’t object.__eq__", mentioned
# in the decision procedure in the FAQ, holds:
assert ListVector.__eq__ is list.__eq__ # because I forgot to override that
assert ListVector.__eq__ is not object.__eq__ # because list.__eq__ is not object.__eq__
assert TupleVector.__eq__ is not tuple.__eq__ # because I remembered that override
assert TupleVector.__eq__ is not object.__eq__ # definitely not
< /code>
Die (überraschende) Ausgabe ist: < /p>
TupleVector.__eq__ called
TupleVector.__eq__ called
< /code>
Ich habe das stattdessen erwartet, "TupleVector.__eq__ called< /code> "sollte
nur einmal statt zweimal emittiert werden,
und der"assert ListVector((1,2,3)) == TupleVector((1,2,3))