Python tut nicht ignorieren __eq__
und __lt__
, zumindest nicht, wenn Sie @functools.total_ordering
tatsächlich verwendet:
>>> from functools import total_ordering
>>> @total_ordering
... class Symbol:
... def __init__(self, name, is_terminal=False):
... self.name = name
... self.is_terminal = is_terminal
... def __repr__(self):
... return 'Symbol({0.name!r}, is_terminal={0.is_terminal!r})'.format(self)
... def __hash__(self):
... return hash(self.name)^hash(self.is_terminal)
... def __eq__(self, other):
... print('{} __eq__ {}'.format(self, other))
... return (self.is_terminal, self.name) == (other.is_terminal, other.name)
... def __lt__(self, other):
... print('{} __lt__ {}'.format(self, other))
... return (self.is_terminal, self.name) < (other.is_terminal, other.name)
...
>>> symbols = set()
>>> for s in "abcdef":
... symbols.add(Symbol(s))
...
>>> sorted(symbols)
Symbol('f', is_terminal=False) __lt__ Symbol('c', is_terminal=False)
Symbol('a', is_terminal=False) __lt__ Symbol('f', is_terminal=False)
Symbol('a', is_terminal=False) __lt__ Symbol('f', is_terminal=False)
Symbol('a', is_terminal=False) __lt__ Symbol('c', is_terminal=False)
Symbol('b', is_terminal=False) __lt__ Symbol('c', is_terminal=False)
Symbol('b', is_terminal=False) __lt__ Symbol('a', is_terminal=False)
Symbol('d', is_terminal=False) __lt__ Symbol('c', is_terminal=False)
Symbol('d', is_terminal=False) __lt__ Symbol('f', is_terminal=False)
Symbol('e', is_terminal=False) __lt__ Symbol('c', is_terminal=False)
Symbol('e', is_terminal=False) __lt__ Symbol('f', is_terminal=False)
Symbol('e', is_terminal=False) __lt__ Symbol('d', is_terminal=False)
[Symbol('a', is_terminal=False), Symbol('b', is_terminal=False), Symbol('c', is_terminal=False), Symbol('d', is_terminal=False), Symbol('e', is_terminal=False), Symbol('f', is_terminal=False)]
In der Tat, Sortierung funktioniert auch ohne @total_ordering
weil die Timsort Implementierung nur __lt__
für diesen Satz verwendet.
Ein Sortierschlüssel ist auch eine Option, geben Sie einfach die (is_terminal, name)
Tupel aus dem Schlüssel:
>>> sorted(symbols, key=lambda s: (s.is_terminal, s.name))
[Symbol('a', is_terminal=False), Symbol('b', is_terminal=False), Symbol('c', is_terminal=False), Symbol('d', is_terminal=False), Symbol('e', is_terminal=False), Symbol('f', is_terminal=False)]
Beachten Sie, dass jetzt die __lt__
Methode nie genannt wird, weil die Sortierschlüssel stattdessen verwendet wird.
Sortierung verwendet definitiv diese Methoden. Wie haben Sie festgestellt, dass sie nicht verwendet werden? Und warum ist ein Sortierschlüssel kein Workaround? 'key = Lambda s: (s.is_terminal, s.name)' würde Ihnen das gleiche Ergebnis geben. –
Was ist das erwartete Ergebnis? Was bekommst du stattdessen? –
Ihre 'Symbol' Klasse ist sortierbar, aber nicht wie geschrieben waschbar. Wenn Sie "__eq__" definieren, müssen Sie auch "__hash__" definieren oder Sie können die Instanzen nicht als Wörterbuchschlüssel verwenden oder sie zu Sätzen hinzufügen. Wenn Sie 'Symbole' in eine Liste geändert haben (und' append' statt 'add' in der Schleife verwenden), würde Ihr Code gut funktionieren. – Blckknght