python - 为什么 set() 构造函数比 list() 慢

标签 python list performance set

我对 set()list() 构造函数进行了计时。 set() 明显慢于 list()。我使用不存在重复项的值对它们进行基准测试。我知道设置使用哈希表是它速度较慢的原因吗?

截至撰写本文时,我正在使用 Python 3.7.5 [MSC v.1916 64 位 (AMD64)]、Windows 10(第 8 期) 三月)。

#No significant changed observed.
timeit set(range(<b>10</b>))
<b>517 ns</b> ± 4.91 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
timeit list(range(<b>10</b>))
<b>404 ns</b> ± 4.71 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

当大小增加时,set() 变得比 list() 慢得多

# When size is 100
timeit set(range(<b>100</b>))
2.13 <b>µs</b> ± 12.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
timeit list(range(<b>100</b>))
934 <b>ns</b> ± 10.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

# when size is ten thousand.
timeit set(range(<b>10000</b>))
<b>325 µs</b> ± 2.37 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
timeit list(range(<b>10000</b>))
<b>240 µs</b> ± 2.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# When size is one million.
timeit set(range(<b>1000000</b>))
<b>86.9 ms</b> ± 1.78 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
timeit list(range(<b>1000000</b>))
<b>37.7 ms</b> ± 396 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

它们都渐近O(n)。当没有重复项时,set(...) 不应大约等于 list(...)

令我惊讶的是,集合理解列表理解并没有表现出像set()list()那样巨大的偏差 显示。

# When size is 100. 
timeit {i for i in range(<b>100</b>)}
<b>3.96 µs</b> ± 858 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
timeit [i for i in range(<b>100</b>)]
<b>3.01 µs</b> ± 265 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# When size is ten thousand.
timeit {i for i in range(<b>10000</b>)}
<b>434 µs</b> ± 5.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
timeit [i for i in range(<b>10000</b>)]
<b>395 µs</b> ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# When size is one million.
timeit {i for i in range(<b>1000000</b>)}
<b>95.1 ms</b> ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
timeit [i for i in range(<b>1000000</b>)]
<b>87.3 ms</b> ± 760 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

最佳答案

为什么它们应该相同?是的,它们都是 O(n),但是 set() 需要对每个元素进行哈希,并且需要考虑元素不唯一。这意味着每个元素的固定成本更高。

Big O 没有提及绝对时间,只提及随着输入大小的增加所花费的时间将如何增长。给定相同的输入,两个 O(n) 算法完成所需的时间可能相差很大。您只能说,当输入大小加倍时,这两个函数所花费的时间将(大致)加倍。

如果你想更好地了解Big O,我强烈推荐Ned Batchelder’s introduction to the subject .

When there are no duplicates shouldn't set(...) approximately equal be to list(...).

不,它们不相等,因为 list() 不进行哈希处理。没有重复项并不说明。

To my suprise set comprehension and list comprehension didn't show those huge deviations like set() and list() showed.

Python 解释器循环执行的附加循环会增加开销,从而影响所用时间。 set() 较高的固定成本就不那么突出了。

还有其他差异可能会产生影响:

  • 给定一个已知长度的序列list()可以预先分配足够的内存来容纳这些元素。集合无法预分配,因为它们不知道会有多少重复项。预分配避免了动态增长列表的(摊销)成本。
  • 列表推导式和集合推导式一次添加一个元素,因此列表对象无法预分配,从而略微增加了每项的固定成本。

关于python - 为什么 set() 构造函数比 list() 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60586807/

相关文章:

arrays - Pyspark 数据框 : Count elements in array or list

sql - 有关最佳SQL性能更新和/或计算现有库存总数的建议

python - 更改数据框副本中的值会更改原始数据框本身

python - 如何使使用 Discord.py 机器人登录的帐户加入特定服务器

c# - Linq for rank() 在 SQL Server 中等效 -

r - 如何设置一个列表,显示每组目标变量的百分比

c# - 使用 ffmpeg 时如何提高图像导出/提取速度?

css - 子选择器和后代选择器在性能上有区别吗?

python - Pandas 根据多行和条件进行计算

python - 自举 Pyramid 中的日志记录设置问题