Much to my own frustration, I managed to make a list of objects in python such that the following fails:
if foo in lst:
lst.index(foo) # ValueError: <foo> is not in list
I assure you, no trickery here:
foo
is an object with a custom __hash__
and __eq__
, and is not being modified elsewherelst
is a standard python []
with no cursesThe only difference between obj in listobject
(or listobject.__contains__(obj)
) and listobject.index()
is that comparison is inverted.
list_contains
does:
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
Py_EQ);
while listindex
does;
for (i = start; i < stop && i < Py_SIZE(self); i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
where el
and v
are the looked-for object, and PyList_GET_ITEM(a, i)
and self->ob_item[i]
are the objects contained in the list.
So lst.index()
throws a ValueError
exception because all of the other.__eq__(foo)
calls return False
and foo.__eq__(other)
is never consulted. foo in lst
works because foo.__eq__(other)
does return True
for at least one value.
You haven't given us a sample list and __eq__
implementation to verify why __eq__
returns False
for all other.__eq__(foo)
calls.