【问题标题】:Python If vs. While?Python If vs. While?
【发布时间】:2011-08-08 17:32:34
【问题描述】:

我有一个小文件读取例程,我只想要它工作的第 200 条记录,但在此过程中我无法弄清楚使用“while”构造有什么问题。 此代码有效:

import csv, sys, zipfile
sys.argv[0] = "/home/tom/Documents/REdata/AllListing1RES.zip"
zip_file    = zipfile.ZipFile(sys.argv[0])
items_file  = zip_file.open('AllListing1RES.txt', 'rU')
rows = []
for row_index, row in enumerate(csv.DictReader(items_file, dialect='excel', delimiter='\t')):
    if (row_index < 200):
        rows.append(row)
    else : break

这段代码一直运行,直到它因内存不足而失败,我认为它是等效的?

import csv, sys, zipfile
sys.argv[0] = "/home/tom/Documents/REdata/AllListing1RES.zip"
zip_file    = zipfile.ZipFile(sys.argv[0])
items_file  = zip_file.open('AllListing1RES.txt', 'rU')
rows = []
for row_index, row in enumerate(csv.DictReader(items_file, dialect='excel', delimiter='\t')):
    while (row_index < 200):
        rows.append(row)
    else : break

那么使用 while 的正确构造是什么? -

【问题讨论】:

  • 请不要将 cmets 添加到您自己的问题中。请更新问题以完成。然后你可以删除混乱和多余的评论。

标签: python if-statement while-loop


【解决方案1】:

所以我很好奇什么会更快,并在 VB.NET 中做了一个快速示例。我不知道我提出的代码是否存在逻辑错误,但是当只执行 100000 次循环时,while 循环会更快。

当拥有大量数据时,时间差会很大。

与主题无关,但不知何故它适合 IF 与 WHILE。

Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim watch As New Stopwatch
        Dim i As Integer = 0

        For loops As Integer = 0 To 100000000

            watch.Start()
            If True Then
                i += 1
            End If
            watch.Stop()
        Next
        MessageBox.Show(watch.ElapsedMilliseconds) ' 2740
    End Sub
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim watch As New Stopwatch
        Dim loops As Integer = 0

        watch.Start()
        While loops < 100000000
            loops += 1
        End While
        watch.Stop()

        MessageBox.Show(watch.ElapsedMilliseconds) ' 300
    End Sub
End Class

【讨论】:

    【解决方案2】:

    编写该循环的更传统方式是:

    for row_index, row in enumerate(csv.DictReader(items_file, dialect='excel', delimiter='\t')):
        if (row_index >= 200):
            break
        rows.append(row)
    

    只要行计数器达到 200,我们就会退出循环。

    要使用while 循环而不是for 循环(请注意,作为循环结构,whilefor 的替代品,而不是if),需要逐步执行手动迭代器:

    itr = enumerate(csv.DictReader(items_file, dialect='excel', delimiter='\t'))
    row_index = -1
    while row_index < 199:
        try:
            row_index, row = next(itr) # Python 3. Use itr.next() in Python 2
        except StopIteration:
            break # Ran out of data
        rows.append(row)
    

    综上所述,itertools 模块中实际上有一个优于这两个选项的替代方案:

    from itertools import islice
    itr = csv.DictReader(items_file, dialect='excel', delimiter='\t')
    rows = list(islice(itr, 200))
    

    【讨论】:

      【解决方案3】:

      它们不等价,因为在您的 while 循环中,它的条件为 row_index &lt; 200,它永远不会为假,因为在您处于该循环中时,row_index 永远不会改变。

      这就是为什么你得到一个内存条件,因为你可能会陷入一个无限循环。

      你实际上是在说:

      伪代码:

      stay in block one as long as row_index < 200:
      
      block_one:
         rows.append(row)
         goto block_one
      

      您可以看到 row_index 永远不会改变,因此您将永远处于 block_one 中。

      而 if 语句具有以下伪代码:

      if row_index < 200 goto block_one otherwise break:
      
        block_one:
          rows.append(row)
      

      您可以看到 block_one 不会像您在 while 循环中看到的那样回到自身。

      【讨论】:

      • 当您希望代码块在某些条件成立时重复运行时。
      • Python 没有名为 where 的构造。过滤语句为if
      • 所以“For”和“While”都在创建循环,“if”只是测试......但没有简单的方法来使用“While”,因为迭代器需要“for”宣言? – @Ncoughlan,感谢您的完整解释!
      【解决方案4】:

      它们不能等效,因为在您的第一个代码中,只有一个循环在迭代(for 循环),它在 row_index 的每次迭代中检查 if-else 语句。在您的第二个代码中,while 循环是一个嵌套循环,其中未达到条件(因为没有迭代 row_index)。这使它进入一个无限循环,在那里给出内存错误。

      【讨论】:

        【解决方案5】:

        在第二种情况下,您永远卡在 while 循环中一遍又一遍地附加同一行...

        【讨论】:

          猜你喜欢
          • 2015-09-10
          • 2014-03-27
          • 2023-03-17
          • 1970-01-01
          • 2015-08-23
          • 2011-04-25
          • 2012-05-30
          • 2018-06-23
          相关资源
          最近更新 更多