【问题标题】:When to use the reversed builtin instead of list slicing何时使用 reversed 内置函数而不是列表切片
【发布时间】:2014-10-19 14:51:09
【问题描述】:

在python中,有很多方法可以反转一个序列:

l = [1,2,3]
reversed(l) #returns a reverse iterator
l[::-1] #returns a reverse sequence

虽然有一个专门用于反转序列的内置函数,但使用列表切片更简洁。另外,列表切片返回一个完整的Sequence,它支持__getitem____len__,而reversed只是一个迭代器。最后,reversed 需要Sequence,这意味着列表切片几乎总是可以工作的。

与列表切片相比,使用 reversed 内置函数有哪些优势?

【问题讨论】:

    标签: python list python-3.x reverse


    【解决方案1】:

    list[::-1] 返回列表的新反向副本。它会根据列表的大小消耗更多的内存:列表对象的大小 + sizeof(pointer) * len(list)

    如果您一次不需要整个列表项,就内存而言,使用reversed 更可取。 (例如,迭代列表倒序,一项一项的处理并不需要一次处理所有项。)

    【讨论】:

    • 它不会像原始列表那样消耗内存,因为新列表中的指针仍然指向内存中的相同对象(浅拷贝)。额外的内存将是 列表对象的大小 + 4 * len(lst)。(每个指针 4 个,在我的系统上,一个空列表的大小约为 36 字节)
    • @AshwiniChaudhary,感谢您指出这一点。我相应地更新了答案。
    【解决方案2】:

    说“reversed 需要一个序列”并不完全正确。在 Python 2.6+ 中,reversed 适用于任何定义了 __reversed__ 方法的对象。因此它可以在不支持整数索引的对象上工作,而切片则不能。

    因此,当仅反转序列的一部分时使用切片,一次需要多个元素,或者可能需要控制步长。如果您只需要遍历每个元素(根据@falsetru 答案的内存考虑),或者如果您有一个具有自定义反转行为的对象,请使用reversed

    【讨论】:

      【解决方案3】:

      哦,该死,评论者指出 rev_func 没有返回列表,它返回的是列表迭代器。哎呀

      当我更正它时,结果基本相同。

      使用 [::-1]:1.6161760782445813 使用 reversed():1.7324838771408098

      import timeit
      import random
      
      def rev_slice(big_list):
          return big_list[::-1]
      
      
      def rev_func(big_list):
      
          #return reversed(big_list)
          return list(reversed(big_list))
      
      
      big_list = [random.random() for i in range(10000000)]
      
      slice_t = timeit.Timer("foo = rev_slice(big_list)", "from __main__ import big_list, rev_slice")
      slice_time = slice_t.timeit(10)
      print ("Using [::-1]: {0}".format(slice_time))
      
      func_t = timeit.Timer("foo = rev_func(big_list)", "from __main__ import big_list, rev_func")
      func_time = func_t.timeit(10)
      print ("Using reversed(): {0}".format(func_time))
      

      【讨论】:

      • 这是因为 reversed 返回一个迭代器,在该过程中没有发生列表创建或循环。所以这根本不取决于列表大小,因此是恒定的时间。
      • 哦,该死的,是的,你是对的。并且一旦修复,结果基本上是相同的,对于 reversed() 可能会慢一点。
      猜你喜欢
      • 2017-07-27
      • 2017-07-22
      • 2021-07-16
      • 2021-06-30
      • 1970-01-01
      • 2023-03-12
      • 2021-08-12
      • 2016-09-16
      • 2017-10-01
      相关资源
      最近更新 更多