使用 n = len(s)而不是直接使用len(s)来计算速度更快吗?

4

通常为了节省时间,我想在我的本地函数中使用n = len(s)。 我很好奇哪一个调用更快,或者它们是相同的吗?

while i < len(s):
  # do something

vs

while i < n:
  # do something

这两种方法差异不大,但使用len(s)时需要先获取s,然后调用s.length,这是O(1) + O(1)。而使用n,则为O(1)。我假设如此。


6
O(1) + O(1) 仍然是 O(1)。在考虑缓存返回值之前,应该对代码进行性能分析,以查看重复调用 len(s) 是否会产生任何显着的开销。请注意,如果循环中 s 的值发生更改,则这样做是 不正确 的。 - chepner
1
显而易见的含义是s在循环中不会改变。任何运行时优化都将使这两个表达式等效。然而,显而易见的(?)答案是你正在询问错误的实体:使用timeit分别计时,看看在你的应用程序中哪一个更快。 - Prune
2
过早的优化是万恶之源……除非这是时间关键流程的内部循环,否则你应该做最易维护的事情,而不是最快的事情……这一点可以通过以下事实得到证明:这两个东西所做的不一样:一个对块长度的更改敏感,另一个则不敏感。 - TemporalWolf
1
@Pythoner 大O符号是“理论上的”。如果你不谈论算法复杂度,那就不要谈论大O符号。 - juanpa.arrivillaga
1
如果你所说的“proper”是指正确,那么这样说显然不太恰当。要更加准确和正确地表达,你可以这样说:“它具有相同的时间复杂度,但常数因子更高。” - juanpa.arrivillaga
显示剩余4条评论
2个回答

7

IT必须更快。

  • 使用n,您只需查看一次变量(字典)。
  • 使用len(s),您需要查看两次(len也是一个我们要查找的函数)。然后调用该函数。

话虽如此,如果使用while i < n:,大多数情况下您可以通过经典的for i in range(len(s)):循环来实现,因为上限不会更改,并且仅在range的开始处被评估一次(这可能会让您想到:我为什么不直接迭代元素或使用enumerate

while i < len(s)允许将索引与可变列表进行比较。这就是重点所在。如果您固定了边界,则变得不太吸引人。

for循环中,使用continue轻松跳过增量(像忘记递增i并最终出现无限while循环一样容易)


5

你说得对,这里有一些基准测试:

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 你说得对,它已经更新了,但原始观点仍然存在。谢谢。 - Rocky Li
我很惊讶它与字面上相比没有太大变化。 - Jean-François Fabre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接