复杂列表理解比直接循环慢

2024-04-25 09:12:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我在leetcode上看到了一个关于编程练习的有趣解决方案,它甚至与问题/解决方案本身无关,因此如果您愿意,可以在提供的链接上阅读它。然而,一个高投票率的解决方案是:

代码段1

def fizzBuzz2(n):
    return  ["Fizz" * (not i%3) + "Buzz" * (not i%5) or str(i) for i in range(1, n+1)]

代码段2

^{2}$

然而,我本以为列表理解将击败普通循环,但当我计时时,情况并非如此。即使是做dis,snippet2也有更多的指令。在

是什么使代码片段1变得缓慢?在


Tags: orforreturn链接def代码段编程not
3条回答

很多人已经回答了你的问题,但我想补充一点,还有更快的解决办法。对我来说,事后检验这些数字似乎是错误的,尽管你已经知道“嘶嘶”、“嗡嗡”和“嘶嘶”会出现在哪些地方。试试这个:

def fizz_buzz(n):
    result = []
    for i in range(1, n + 1, 15):
        result += [str(i), str(i + 1), 'Fizz',
                   str(i + 3), 'Buzz', 'Fizz',
                   str(i + 6), str(i + 7), 'Fizz', 'Buzz',
                   str(i + 10), 'Fizz', str(i + 12), str(i + 13),
                   'FizzBuzz']
    return result[:n - len(result)]

start_time = time()
for i in range(10000):
    fizz_buzz(1000)
print("fizz_buzz:", time() - start_time)

与前面的答案相比:

^{pr2}$

你的片段

def fizzBuzz2(n):
    return  ["Fizz" * (not i%3) + "Buzz" * (not i%5) or str(i) for i in range(1, n+1)]

执行大量字符串连接(即使是空字符串)。我用一个额外的模运算来交换它,它节省了连接,而且它已经更快了。在

^{pr2}$

顺便说一句,在我的机器上,这两种理解都比“经典”方法更快,所以我得到的结果与你所说的不同:

your comp: 4.927702903747559
my listcomp: 4.343341112136841
classical: 6.015967845916748

所以我优化的listcomp赢了(在您的机器上似乎也赢了),即使我对listcomp的流控制所引起的额外模操作不满意)

我的测试协议使用n=1000执行操作10000次:

import time
start_time = time.time()
for i in range(10000):
    fizzBuzz2(1000)
print("your comp:",time.time()-start_time)
start_time = time.time()
for i in range(10000):
    fizzBuzz3(1000)
print("my listcomp:",time.time()-start_time)
start_time = time.time()
for i in range(10000):
    fizzBuzz(1000)
print("classical:",time.time()-start_time)

请注意,即使在“经典”方法中预先计算模,它也会下降到5.375272035598755秒(这很好),但由于所有的指令,它仍然比listcomp差(您还通过调用一个方法来保存模计算来降低listcomp的速度)。在这种情况下,python不是获得最快速度的合适语言。在

是的,因为在理解中,所有的指令都在每个循环中被评估。在

Snippet 2atmost 1if分支中求值。因此,减少了计算量,使之成为一种更快的替代方法。在

相关问题 更多 >