简体   繁体   English

Python If vs. While?

[英]Python If vs. While?

I have a small file read routine and I want only the 1st 200 records I have it working but along the way I could not figure out what was wrong with using the "while" construct. 我有一个小文件读取例程,我只想要我有它的前200条记录,但是我一直无法弄清楚使用“while”构造有什么问题。 This code works: 此代码有效:

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

This code runs until it fails with an out of memory condition I would have thought it was equivalent? 这段代码一直运行,直到它失败并出现内存不足的情况我认为它是等效的?

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

so what would be the right construct using while? 那么什么是正确的构造使用时? -

They are not equivalent because in your while loop, it has the condition of row_index < 200 , which will never be false because row_index will never change while you are in that loop. 它们不是等价的,因为在你的while循环中,它具有row_index < 200的条件,它永远不会为false,因为row_index在你进入该循环时永远不会改变。

This is why you are getting a memory conditional because you are probably running into an infinite loop. 这就是为什么你得到一个条件的内存,因为你可能遇到了无限循环。

You are essentially saying: 你基本上是这样说的:

Psuedo Code: Psuedo代码:

stay in block one as long as row_index < 200:

block_one:
   rows.append(row)
   goto block_one

You can see that row_index will never change, thus you are going to be in block_one forever. 你可以看到row_index永远不会改变,因此你将永远在block_one中。

Whereas the if statement has the following psuedo code: 而if语句具有以下伪代码:

if row_index < 200 goto block_one otherwise break:

  block_one:
    rows.append(row)

You can see that block_one is not going back to itself, like you see in the while loop. 您可以看到block_one不会回归自身,就像您在while循环中看到的那样。

The more traditional way of writing that loop would be: 编写该循环的更传统方式是:

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

As soon as the row counter hits 200, we bail out of the loop. 一旦行计数器达到200,我们就会退出循环。

To use a while loop instead of a for loop (note that, as a looping construct, while is an alternative to for rather than to if ) it is necessary to step through the iterator manually: 使用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)

All that said, there's actually a superior alternative to both of these options available in the itertools module: 所有这一切,实际上是itertools模块中可用的这两个选项的优越替代方案:

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

So I was curious what would be faster and did a quick example in VB.NET. 所以我很好奇什么会更快,并在VB.NET中做了一个快速的例子。 I don't know if the code I came up with has a logical errors but when doing only 100000 loops the while loops is faster. 我不知道我提出的代码是否存在逻辑错误,但是当只执行100000次循环时,while循环更快。

When having large numbers of data the time difference is hugh. 当拥有大量数据时,时间差异很大。

Has nothing to do with the topic but somehow it fits the IF vs 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

在第二种情况下,你永远陷入了while循环,一遍又一遍地追加同一行......

They can't be equivalent because in your first code, only one loop is iterating (the for loop) which checks the if-else statements at each iteration of row_index. 它们不能等价,因为在第一个代码中,只有一个循环是迭代的(for循环),它在row_index的每次迭代中检查if-else语句。 In your second code, the while loop is a nested loop in which the condition isn't being reached (since there is nothing iterating the row_index). 在第二个代码中,while循环是一个嵌套循环,其中没有达到条件(因为没有迭代row_index)。 that makes it go into an infinite loop, there by giving the memory error. 这使得它进入无限循环,通过给出内存错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM