【问题标题】:Which gives better performance: len(a[:-1]) or len(a)-1提供更好的性能: len(a[:-1]) 或 len(a)-1
【发布时间】:2014-04-23 03:45:17
【问题描述】:

在性能方面更好的 Python 中:

1)

for i in range(len(a[:-1])):
    foo()

2)

for i in range(len(a)-1):
    foo()

更新:

关于我为什么要循环索引的一些上下文(非惯用语?):

for c in reversed(range(len(self._N)-1)):
    D[c] =  np.dot(self._W[c], D[c-1])*A[c]*(1-A[c])

【问题讨论】:

  • a[:-1] 创建一个新的字符串/列表(这是不必要的),而 len(a) 只返回长度。现在,你认为哪一个更好?

标签: python range slice


【解决方案1】:

第二个更好,两个原因:

  1. 第一个创建了新列表a[:-1]占用了不必要的时间和内存,第二个没有创建新列表。

  2. 第二个更直观清晰。

[:] 返回列表的shallow copy。这意味着每个切片符号都会返回一个列表,该列表在内存中具有新地址,但其元素将具有与源列表元素相同的地址。

【讨论】:

    【解决方案2】:

    range(0, len(a) - 1) 应该是这两个选项中性能更高的。另一个制作序列的不必要副本(无 1 个元素)。对于这样的循环,您甚至可以通过在 python2.x 上使用 xrange 来提高性能,因为这样可以避免从 range 调用中实现列表。

    当然,您通常不需要在 python 中循环索引——通常有更好的方法。

    【讨论】:

    • @mgilson 好点,我添加了一些关于为什么要循环索引的上下文。
    • @mgilson 感谢您的 xrange 提示!
    【解决方案3】:

    表达式a[:-1] 创建一个新列表,您获取该列表的长度并丢弃该列表。这是 O(n) 时间和空间复杂度,与第二个示例的 O(1) 时间和空间复杂度相比。

    【讨论】:

    • 老实说,时间复杂度几乎可以肯定不会产生明显的差异......即使对于巨大的列表..
    • @JoranBeasley 我希望既然 OP 在问这个问题,他们实际上是在足够大的列表上运行,这会有所作为。
    • 好吧,你们是完全正确的......这就是我只是略读这个问题所得到的(我什至没有意识到它是在询问性能,直到我的回答中有评论:P)(+1)
    • 对于a = [None] * 10000,我看到timeit 的差异约为 1000 倍(50 µs 与 80 ns)
    【解决方案4】:

    这两种方法都不对

    for i,item in enumerate(a[:-1]):
        ...
    

    你应该怎么做...

    在 python 中你永远不应该这样做

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

    这是时间差异

    >>> timeit.timeit("for i in range(len(a)-1):x=i","a=range(1000000)",number=100)
    3.30806345671283
    >>> timeit.timeit("for i in enumerate(a[:-1]):x=i","a=range(1000000)",number=100
    5.3319918613661201
    

    如您所见,在大量整数上执行 100 次需要额外的 2 秒...但恕我直言,这仍然是一个更好的主意

    【讨论】:

    • 既然这个问题是关于性能的,那么在enumerate 中制作列表副本不会影响性能吗?
    • 易于测试...等等...我怀疑它会非常微不足道
    • 对于足够大的 len(a) 值来说代价高昂。
    • @JoranBeasley -- 测试起来并不容易。您对 OP 输入的大小/类型一无所知……尽管在大多数情况下,这确实无关紧要……
    • 我已经完成了足够多的高性能编程,知道优雅和高效通常是相互排斥的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 2018-06-30
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    相关资源
    最近更新 更多