`in`的行为与python列表中的`index`有什么不同

时间:2014-04-22 17:47:46

标签: python list python-3.x containment

令我非常沮丧的是,我设法在python中创建一个对象列表,以便以下操作失败:

if foo in lst:
    lst.index(foo) # ValueError: <foo> is not in list

我向你保证,这里没有任何诡计:

  1. foo是一个自定义__hash____eq__的对象,未在其他地方修改
  2. 这两个函数都是幂等的,不会修改状态
  3. lst是一个没有诅咒的标准python []

1 个答案:

答案 0 :(得分:4)

obj in listobject(或listobject.__contains__(obj))与listobject.index()之间的唯一区别是比较倒置

list_contains

for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
    cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
                                       Py_EQ);

listindex会这样做;

for (i = start; i < stop && i < Py_SIZE(self); i++) {
    int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);

其中elv是查找对象,PyList_GET_ITEM(a, i)self->ob_item[i]是列表中包含的对象。

因此lst.index()会引发ValueError个异常,因为所有other.__eq__(foo)次调用都会返回False,而且foo.__eq__(other)永远不会被查阅。 foo in lst有效,因为foo.__eq__(other)确实会为至少一个值返回True

您尚未向我们提供示例列表和__eq__实施,以验证 __eq__False次调用返回other.__eq__(foo)的原因