在 python 中使用 in 运算符搜索列表时使用啥算法?

Posted

技术标签:

【中文标题】在 python 中使用 in 运算符搜索列表时使用啥算法?【英文标题】:What algorithm is used when using the in operator in python to search a list?在 python 中使用 in 运算符搜索列表时使用什么算法? 【发布时间】:2012-05-15 03:46:30 【问题描述】:

当使用“in”运算符搜索列表中的项目时,例如

if item in list:
  print item

使用什么算法来搜索这个项目。是从头到尾直接搜索列表还是使用二进制搜索之类的方法?

【问题讨论】:

in,按顺序遍历项目,没有搜索 @RC。 : 当然,lists 是这样。但对于其他容器并非如此(例如,集合使用哈希表 - 请参阅 setobject.c 第 689 行中的 set_contains_entry()。) @Li-aungYip 感谢您的澄清 【参考方案1】:

lists 不能被假定为已排序(或任何顺序),因此二进制搜索不起作用。也不能假定键是可散列的,因此与 dictset 不同,不能使用散列表查找来加速搜索

据推测,这是从第一个到最后一个元素的直接检查。

我会尝试挖掘相关的 Python 源代码。

--

编辑:实现in 运算符的Python list.__contains__() 函数在listobject.c 中定义:

   393 static int
   394 list_contains(PyListObject *a, PyObject *el)
   395 
   396     Py_ssize_t i;
   397     int cmp;
   398 
   399     for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
   400         cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
   401                                            Py_EQ);
   402     return cmp;
   403 

它遍历列表中的每个元素,从第一个元素到最后一个元素(或直到找到匹配项。)这里没有捷径。

--

编辑 2:情节变厚了。如果 Python 检测到您正在测试 constant listset 中某个元素的成员资格,例如:

if letter in ['a','e','i','o','u']:    # list version
if letter in 'a','e','i','o','u':    # set version

编辑 3 [@JohnMachin]:

常量列表在 2.5-2.7 和 3.1-3.3 中优化为常量元组。 常量集在 3.3 中优化为(常量)frozenset。

另见@CoryCarson 的回答。

【讨论】:

常量列表在 2.5-2.7 和 3.1-3.3 中优化为常量tuple @JohnMachin:所以不是针对in 运算符的哈希表查找?请随时编辑我的答案以确保准确性。【参考方案2】:

如果list 是文字列表,Python 3.2+ 将采用更快的方法:http://docs.python.org/dev/whatsnew/3.2.html#optimizations

【讨论】:

哦,非常好。需要明确的是,该特定更改说明似乎是在谈论将常量 sets 转换为 frozensets - 我认为常量 lists 的优化早于此。

以上是关于在 python 中使用 in 运算符搜索列表时使用啥算法?的主要内容,如果未能解决你的问题,请参考以下文章

mysql-connector python 'IN' 运算符存储为列表

Python“in”关键字对排序列表的效率

元组数据结构支持 in 运算符吗

9.算法之顺序二分hash查找

元组数据结构支持 in 运算符吗

无法使用“in”运算符在未定义中搜索“X”