为什么 `{*l}` 比 `set(l)` 快 - python 集合(实际上不仅针对集合,还针对所有序列)
Why is `{*l}` faster than `set(l)` - python sets (not really only for sets, for all sequences)
这是我的时间安排:
>>> import timeit
>>> timeit.timeit(lambda: set(l))
0.7210583936611334
>>> timeit.timeit(lambda: {*l})
0.5386332845236943
为什么会这样,我的意见是平等的,但事实并非如此。
所以从这个例子中解包很快,对吧?
同理;解释器包括对使用专门代码路径的基于语法的操作的专门支持,而构造函数调用涉及:
- 从内置范围加载构造函数(需要一对
dict
查找,一个在全局范围内,另一个在失败时在内置范围内)
- 需要通过通用可调用调度机制和通用参数解析代码进行调度,所有这些都比将其所有参数作为 C 数组从堆栈中读取的单字节代码昂贵得多
所有这些优点都与固定开销相关;两种方法的大 O 是相同的,所以 {*range(10000)}
不会比 set(range(10000))
快 noticeably/reliably,因为实际的构建工作大大超过了通过加载和调用构造函数的开销通用调度。
这是我的时间安排:
>>> import timeit
>>> timeit.timeit(lambda: set(l))
0.7210583936611334
>>> timeit.timeit(lambda: {*l})
0.5386332845236943
为什么会这样,我的意见是平等的,但事实并非如此。
所以从这个例子中解包很快,对吧?
同理
- 从内置范围加载构造函数(需要一对
dict
查找,一个在全局范围内,另一个在失败时在内置范围内) - 需要通过通用可调用调度机制和通用参数解析代码进行调度,所有这些都比将其所有参数作为 C 数组从堆栈中读取的单字节代码昂贵得多
所有这些优点都与固定开销相关;两种方法的大 O 是相同的,所以 {*range(10000)}
不会比 set(range(10000))
快 noticeably/reliably,因为实际的构建工作大大超过了通过加载和调用构造函数的开销通用调度。