Pythonはないを__eq__
を無視し__lt__
んが、実際に@functools.total_ordering
を使用した場合、少なくともではない:
>>> 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)]
実際にTimSort実装が唯一のこのセットのために__lt__
を使用しているため、でもソートは@total_ordering
せずに動作します。ソートキーが代わりに使用されているので、今__lt__
メソッドが呼び出されることはありません
>>> 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)]
注:
ソートキーは、ちょうど鍵から(is_terminal, name)
タプルを返し、またオプションです。
ほとんどの場合、ソートでこれらのメソッドが使用されます。それらが使われていないとあなたはどのように判断しましたか?ソートキーはなぜ回避策ではないのですか? 'key = lambda s:(s.is_terminal、s.name)'は同じ結果を返します。 –
期待される結果は何ですか?代わりに何を得ますか? –
'Symbol'クラスはソート可能ですが、記述されたようにハッシュ可能ではありません。 '__eq__'を定義する場合、' __hash__'を定義する必要があります。または、インスタンスを辞書キーとして使用したり、それらをセットに追加することはできません。 'symbols'をリストに変更した場合(ループで' add'ではなく 'append'を使用します)、あなたのコードはうまく動作します。 – Blckknght