【问题标题】:Is it faster to use n = len(s) instead of using len(s) directly?使用 n = len(s) 而不是直接使用 len(s) 会更快吗?
【发布时间】:2018-11-27 21:08:48
【问题描述】:

通常为了节省一些时间,我希望我们在本地函数中使用 n = len(s)。 我很好奇哪个呼叫更快或它们相同?

while i < len(s):
  # do something

while i < n:
  # do something

应该没有太大的区别,但是使用len(s),我们需要先到达s,然后调用s.length。这是 O(1) + O(1)。但是使用 n,它是 O(1)。我假设是这样。

【问题讨论】:

  • O(1) + O(1) 仍然是 O(1)。在担心缓存返回值之前,您应该分析您的代码以查看对 len(s) 的重复调用是否会产生任何重大开销。请注意,如果s 的值在循环中发生变化,则这样做是不正确的
  • 显而易见的含义是s 在循环内不会改变。任何运行时优化都会使这两个表达式等效。但是,显而易见的 (?) 答案是您询问了错误的实体:time 每次使用 timeit 并查看在您的应用程序中一个是否比另一个更快。
  • 过早的优化是万恶之源...除非这是时间关键过程的内部循环,否则您应该做最可维护的事情,而不是最快的事情... 这两个不做同样的事情的事实:一个对块中的长度变化敏感,而另一个则不敏感。
  • @Pythoner Big-Oh 表示法是“理论上的”。如果您不是在谈论算法复杂性,那就不要谈论大哦。
  • 如果正确的意思是正确的,那肯定是不正确的。为了准确和正确,您可以说“它具有相同的时间复杂度但更高的常数因子”

标签: python variable-length


【解决方案1】:

必须更快。

  • 使用n,您可以在变量(字典)中查找一次。
  • 使用len(s) 会查找两次(len 也是我们必须查找的函数)。然后调用函数。

也就是说,如果您在大多数情况下都使用while i &lt; n:,则可以摆脱经典的for i in range(len(s)): 循环,因为上限不会改变,并且仅在range 开始时评估一次(这可能会导致您to:为什么我不直接迭代元素或使用enumerate

while i &lt; len(s) 允许将您的索引与不同的列表进行比较。这就是重点。如果你修复了界限,它就会变得不那么有吸引力。

for 循环中,使用continue 很容易跳过增量(就像忘记递增i 并以无限while 循环结束一样容易)

【讨论】:

    【解决方案2】:

    你是对的,这里有一些基准:

    s = np.random.rand(100)
    n = 100
    

    以上是设置。

    %%timeit
    50 < len(s)
    
    86.3 ns ± 2.4 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
    

    对比:

    %%timeit
    50 < n
    
    36.8 ns ± 1.15 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
    

    但话又说回来,很难想象约 60ns 级别的差异会影响速度。除非您拨打len(s) 数百万次。

    【讨论】:

    • @Jean-FrançoisFabre 你说得对,它已更新,但原点仍然存在。谢谢。
    • 我很惊讶它与文字相比并没有太大变化。
    猜你喜欢
    • 2014-11-10
    • 1970-01-01
    • 2019-12-27
    • 2016-09-18
    • 1970-01-01
    • 2013-03-06
    • 2021-01-16
    • 1970-01-01
    • 2014-09-21
    相关资源
    最近更新 更多