container.___le___ can use only <=?
Neil Cerutti
horpner at yahoo.com
Wed Dec 19 11:03:27 EST 2007
On 2007-12-15, Carl Banks <pavlovevidence at gmail.com> wrote:
> On Dec 15, 9:05 am, ceru... at tds.net wrote:
>> My reasoning is (I hope) that the container ought to support
>> every comparison operation supported by the contained objects.
>> This can be ensured by being careful in the implementation.
>
> I see what you're asking now. Yep, probably a bad idea to use
> that shortcut.
I put together a test suite, and discovered that the built-in
list assumes that all contained object support __eq__, i.e., it
may call __eq__ while performing some other comparison, e.g.,
__gt__. This is contrary to the rule I was contemplating for
sequence comparisons in this thread.
>>> class Evil:
... def __init__(self, i):
... self.i = i
... def __eq__(self, o):
... raise RuntimeError
... def __gt__(self, o):
... if isinstance(o, Evil):
... return self.i > o.i
... return NotImplemented
...
>>> [Evil(1)] > [Evil(0)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __eq__
RuntimeError
This prompted inspection of listobject.c. After trying some
short-cuts for __ne__ and __eq__, list_richcompare iterates
through both lists until the first non-equal elements are found,
and then performs the correct comparison, or simply returns,
depending on if the lists were the same length.
Otherwise, the built-in list rich comparison follows the advice
posted in this thread, i.e., it uses only the comparison
operation being implemented to compare contained objects.
When implementing a mutable sequence in Python, the rule of thumb
seems to be "do as lists do," so as of the Python's current
implementation, there's a small limit on the perversity level of
the rich comparison operations of types contained in lists.
--
Neil Cerutti
More information about the Python-list
mailing list