【问题标题】:Which is the most efficient way to iterate through a list in python?在python中遍历列表的最有效方法是什么?
【发布时间】:2012-06-07 10:09:57
【问题描述】:

假设我有一个项目列表:

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

我需要为这些项目中的每一项执行一些功能。在某些情况下,我需要返回一个项目的索引。

哪种方法最好、最有效?

for item in list:
    ....

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

【问题讨论】:

  • 发帖前请先搜索论坛。这已被回答一百万次
  • @sulabh:我找不到这个问题的确切副本。请链接相同。我要问的问题是两种不同的迭代列表方式之间的比较,以及哪种方式更好的建议。
  • 如果这不是完全相同的副本,那么人们可以收回他们的反对票吗?我是个穷人,你看...
  • 我会警告不要误认为列表是有效的容器。他们不是。如果您计划迭代大型数据集,则列表效率不高。见下文,应该使用不太灵活但可以处理大小的 numpy 数组。

标签: python performance list


【解决方案1】:
for item in list:

它显然是函数调用较少的那个。

如果您想随时获取项目的索引,请像这样使用enumerate

for pos, item in enumerate(collection):

【讨论】:

    【解决方案2】:
    def loop_1(data):
        for i in range(len(data)):
            print(data[i])
    
    
    def looper_2(data):
        for val in data:
            print(val)
    

    检查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        
    

    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
    

    显然第二个版本更好。

    【讨论】:

      【解决方案3】:

      另一种可能的解决方案是使用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.])
      

      这是一个非常简单的操作,但您可以使用数组作为公式中的简单参数来获得更复杂的操作。对于大型数组,这可能比列表推导要快得多,并且它使代码更清晰、更易于阅读(无需创建函数来映射到列表推导中)。您还可以使用索引和切片来定制您想要做的事情:

      如果您想访问实际的索引位置,请使用 ndenumerate

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

      这个for循环的输出是:

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

      注意:numpy 以元组形式返回的索引以处理其他维度。这里我们只有一个维度,因此您必须解包元组才能获取元素的索引。

      【讨论】:

      • 你能补充一下这方面的细节吗?
      【解决方案4】:

      显然for i in range(len(list)): 会更慢 - 在 python 2 中,它相当于:

      list2 = range(len(list))
      
      for i in list2:
          ...
      

      如果这样更快,那么这会更快,对吧?

      list2 = range(len(list))
      list3 = range(len(list2))
      list4 = range(len(list3))
      
      for i in list4:
          ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-27
        • 1970-01-01
        • 2017-02-03
        • 2013-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多