【发布时间】:2015-09-11 10:48:15
【问题描述】:
通过此处的一篇文章,我了解到使用 next() 搜索和检索列表中第一次出现的元素可能会很快。然而,我很惊讶地看到传统的 for-if-break 语法在相当长的一段时间内表现得更好。如果我在分析中犯了错误,请纠正我。 这是我尝试过的sn-p:
>>> def compare_2():
... device = 'a'
... l = ['a', 'b', 'c', 'd']
... z = next((device for x in l if x==device), None)
>>> def compare_1():
... device = 'a'
... l = ['a', 'b', 'c', 'd']
... z = None
... for x in l:
... if x == device:
... z = device
... break
>>> import timeit
>>> t = timeit.Timer(setup='from __main__ import compare_2', stmt='compare_2()')
>>> t.timeit()
1.5207240581512451
>>> t = timeit.Timer(setup='from __main__ import compare_1', stmt='compare_1()')
>>> t.timeit()
0.46623396873474121
我认为这可能会发生,因为我试图搜索和检索列表中的第一个元素作为示例。我还尝试了最后一个元素,发现 next() 的性能并没有比以前好。
>>> def compare_2():
... device = 'd'
... l = ['a', 'b', 'c', 'd']
... z = next((device for x in l if x==device), None)
...
>>>
>>> def compare_1():
... device = 'd'
... l = ['a', 'b', 'c', 'd']
... z = None
... for x in l:
... if x == device:
... z = device
... break
...
>>>
>>> t = timeit.Timer(setup='from __main__ import compare_2', stmt='compare_2()')
>>> t.timeit()
1.6903998851776123
>>> t = timeit.Timer(setup='from __main__ import compare_1', stmt='compare_1()')
>>> t.timeit()
0.66585493087768555
很想知道在优化代码方面何时实际使用 next() 以及何时不使用。 谢谢!
更新:
if device in l 肯定会更快。
我实际上只是想制作一个简单案例的原型。我在尝试根据属性匹配从对象列表中检索对象时遇到了这个问题。例如:
obj = next(obj for obj_list if obj.value == 1)
【问题讨论】:
-
为什么你认为它会更快? (此外,在这种情况下,
if device in l比您计时的任何一个选项都要好。) -
如果将列表的大小增加到 1M,例如使用
l = range(1000000),然后从比较函数中取出列表结构并将其导入设置中,请设置 device=500000 , 然后你会看到他们有非常相似的时间。if device in l更快。我猜只有在不中断 for 循环并坚持遍历整个列表的情况下,使用 next 和生成器表达式才会更快。正如@TessellatingHeckler 指出的那样,创建生成器会给您带来一些开销,因此对于小型列表来说效率很低。
标签: python list python-2.7 search optimization