简体   繁体   English

在 python 中迭代列表的最有效方法是什么?

[英]Which is the most efficient way to iterate through a list in python?

Say I have a list of items:假设我有一个项目列表:

x = [1, 2, 3, 4, 5]

I need to perform some functions for each of these items.我需要为这些项目中的每一个执行一些功能。 In a certain case, I need to return the index of an item.在某些情况下,我需要返回项目的索引。

Which is the best and most efficient way?哪种方法最好、最有效?

for item in list:
    ....

or要么

for i in range(len(list)):
    ....
for item in list:

its obviously the one with fewer function calls.它显然是函数调用较少的那个。

If you want to get the index of items as you go use enumerate like this如果你想在你去使用enumerate这样的时候获取项目的索引

for pos, item in enumerate(collection):
def loop_1(data):
    for i in range(len(data)):
        print(data[i])


def looper_2(data):
    for val in data:
        print(val)

Checking with dis gives us the following bytecode for loop_1:使用dis检查为我们提供了以下 loop_1 的字节码:

 12       0 SETUP_LOOP              40 (to 43)
          3 LOAD_GLOBAL              0 (range)
          6 LOAD_GLOBAL              1 (len)
          9 LOAD_FAST                0 (data)
         12 CALL_FUNCTION            1
         15 CALL_FUNCTION            1
         18 GET_ITER            
    >>   19 FOR_ITER                20 (to 42)
         22 STORE_FAST               1 (i)

13       25 LOAD_GLOBAL              2 (print)
         28 LOAD_FAST                0 (data)
         31 LOAD_FAST                1 (i)
         34 BINARY_SUBSCR       
         35 CALL_FUNCTION            1
         38 POP_TOP             
         39 JUMP_ABSOLUTE           19
    >>   42 POP_BLOCK           
    >>   43 LOAD_CONST               0 (None)
         46 RETURN_VALUE        

The bytecode for loop_2 looks like this: loop_2 的字节码如下所示:

17        0 SETUP_LOOP              24 (to 27)
          3 LOAD_FAST                0 (data)
          6 GET_ITER            
    >>    7 FOR_ITER                16 (to 26)
         10 STORE_FAST               1 (val)

18       13 LOAD_GLOBAL              0 (print)
         16 LOAD_FAST                1 (val)
         19 CALL_FUNCTION            1
         22 POP_TOP             
         23 JUMP_ABSOLUTE            7
    >>   26 POP_BLOCK           
    >>   27 LOAD_CONST               0 (None)
         30 RETURN_VALUE

The second version is obviously better.第二个版本显然更好。

Another possible solution would be to use numpy which would be very efficient, for large lists perhaps even more efficient than a list comprehension or a for loop.另一种可能的解决方案是使用numpy ,这将非常有效,对于大型列表,可能比列表理解或 for 循环更有效。

import numpy as np

a = np.arange(5.0)   # a --> array([0., 1., 2., 3., 4.])

# numpy operates on arrays element by element 
#
b =3.*a              # b --> array([0., 3., 6., 9., 12.])

This is a pretty simple operation but you can get more complex using an array as simply an argument in a formula.这是一个非常简单的操作,但您可以使用数组作为公式中的简单参数变得更复杂。 For large arrays this can be much faster than a list comprehension and it makes the code cleaner and easier to read (no need to create a function to map in a list comprehension).对于大型数组,这可能比列表理解快得多,并且它使代码更清晰、更易于阅读(无需创建一个函数来映射到列表理解中)。 You can also use indexing and slicing to tailor what you want to do:您还可以使用索引和切片来定制您想要执行的操作:

If you want to have access to the actual index positions use ndenumerate如果您想访问实际的索引位置,请使用 ndnumerate

# b is as above
for i, x in np.ndenumerate(b):
    print i, x

The output of this for loop is:这个 for 循环的输出是:

(0,) 0.0 
(1,) 3.0 
(2,) 6.0 
(3,) 9.0 
(4,) 12.0 

NOTE: the index returned as a tuple by numpy to handle additional dimensions.注意:numpy 作为元组返回的索引以处理其他维度。 Here we only have a single dimension so you'd have to unpack the tuple to get the index of the element.这里我们只有一个维度,因此您必须解压缩元组以获取元素的索引。

Obviously for i in range(len(list)): will be slower - in python 2, it's equivalent to this:显然for i in range(len(list)):会更慢 - 在 python 2 中,它相当于:

list2 = range(len(list))

for i in list2:
    ...

If that were faster, then this would be even faster, right?如果那个更快,那么这会更快,对吧?

list2 = range(len(list))
list3 = range(len(list2))
list4 = range(len(list3))

for i in list4:
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM