为什么Python';s的集合差分方法是否需要空集合的时间?
我的意思是:为什么Python';s的集合差分方法是否需要空集合的时间?,python,performance,set,operators,Python,Performance,Set,Operators,我的意思是: > python -m timeit "set().difference(xrange(0,10))" 1000000 loops, best of 3: 0.624 usec per loop > python -m timeit "set().difference(xrange(0,10**4))" 10000 loops, best of 3: 170 usec per loop 显然,python会遍历整个参数,即使事先知道结果是空集。有什么好的理由吗
> python -m timeit "set().difference(xrange(0,10))"
1000000 loops, best of 3: 0.624 usec per loop
> python -m timeit "set().difference(xrange(0,10**4))"
10000 loops, best of 3: 170 usec per loop
显然,python会遍历整个参数,即使事先知道结果是空集。有什么好的理由吗?代码是在Python2.7.6中运行的
(即使对于非空集合,如果您发现在迭代过程中删除了第一个集合的所有元素,也应该立即停止。)IMO这是一个专业化的问题,请考虑:
In [18]: r = range(10 ** 4)
In [19]: s = set(range(10 ** 4))
In [20]: %time set().difference(r)
CPU times: user 387 µs, sys: 0 ns, total: 387 µs
Wall time: 394 µs
Out[20]: set()
In [21]: %time set().difference(s)
CPU times: user 10 µs, sys: 8 µs, total: 18 µs
Wall time: 16.2 µs
Out[21]: set()
显然,这个差异专门实现了set-set
请注意,差分运算符要求右侧参数为集合,而差分运算符允许任何iterable
Per@wim实现在当Python核心开发人员添加新特性时,首要任务是正确的代码和全面的测试覆盖率。这本身就够难的了。当有人有了想法和倾向时,加速往往会来得晚。我打开了一个跟踪问题,总结了这里讨论的建议和反对理由。我将在这里总结一下它的配置 更新:3.6.0b1中增加了一个开始为空的集合的早期输出,大约在一天内到期 有什么好的理由吗 为空集合设置一个特殊路径以前从未出现过 即使对于非空集,如果您发现在迭代的中途删除了第一个集的所有元素,那么立即停止也是有意义的 这是一个合理的优化要求。我已经做了一个测试,很快就会应用它。以下是应用修补程序后的新计时:
$ py -m timeit -s "r = range(10 ** 4); s = set()" "s.difference(r)"
10000000 loops, best of 3: 0.104 usec per loop
$ py -m timeit -s "r = set(range(10 ** 4)); s = set()" "s.difference(r)"
10000000 loops, best of 3: 0.105 usec per loop
$ py -m timeit -s "r = range(10 ** 4); s = set()" "s.difference_update(r)"
10000000 loops, best of 3: 0.0659 usec per loop
$ py -m timeit -s "r = set(range(10 ** 4)); s = set()" "s.difference_update(r)"
10000000 loops, best of 3: 0.0684 usec per loop
在Python3中甚至更慢:)我想python的制作者没有想到这一点,因为在现实生活中这种情况不应该经常发生。解决方法:在运行差异之前检查设置大小。但是很好!顺便说一句,最近的PyPy也是如此。@Jean-Françoisfare即使对于非空集,如果您发现在迭代过程中删除了第一个集的所有元素,立即停止也是有意义的。我不确定这是否是一个好的理由,但
set.difference
的参数是任意的可数,不仅仅是布景。迭代某些函数的行为可能会产生副作用,让函数在所有情况下都保证相同的行为可能更重要,而不是只在一种情况下让参数“未使用”。特例很好!因此,空集的案例被补丁覆盖。另一个呢?例如,s=set([1])
,r=set(range(10**4))
。我用r
和s
做了一个简单的测试,就像我上次的评论一样,显然当这两个集合都是集合时,它的运行速度非常快,即使第一个集合不是空的。@RaymondHettinger新的实现将保证迭代器总是被完全使用,还是会被保留为未定义?