Python 如果 vs. 循环?

2 投票
5 回答
8511 浏览
提问于 2025-04-16 16:02

我有一个读取小文件的程序,我只想要前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”时,正确的写法应该是什么呢?

5 个回答

0

这两个代码不能等价,因为在你第一个代码里,只有一个循环在运行(就是那个 for 循环),它会在每次 row_index 的变化时检查 if-else 语句。而在你第二个代码里,while 循环是一个嵌套循环,但它的条件没有被满足(因为没有东西在改变 row_index)。这样就会导致它一直循环下去,最终出现内存错误。

6

这两个东西不一样,因为在你的 while 循环里,有个条件是 row_index < 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 循环中那样回到自己。

3

写这个循环的传统方式是这样的:

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 循环(注意,while 循环是 for 的一种替代方式,而不是 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))

撰写回答