在Allen的Think中,摘录13-2要求处理来自gutenberg.org的任何gutenberg.org文件,并跳过以类似于“产生的”结尾的头信息。这是作者给出的解决方案:
def process_file(filename, skip_header):
"""Makes a dict that contains the words from a file.
box = temp storage unit to combine two following word in one string
res = dict
filename: string
skip_header: boolean, whether to skip the Gutenberg header
returns: map from string of two word from file to list of words that comes
after them
Last two word in text maps to None"""
res = {}
fp = open(filename)
if skip_header:
skip_gutenberg_header(fp)
for line in fp:
process_line(line, res)
return res
def process_line(line, res):
for word in line.split():
word = word.lower().strip(string.punctuation)
if word.isalpha():
res[word] = res.get(word, 0) + 1
def skip_gutenberg_header(fp):
"""Reads from fp until it finds the line that ends the header.
fp: open file object
"""
for line in fp:
if line.startswith('Produced by'):
break我真的不明白这段代码中的执行缺陷。一旦代码开始使用skip_gutenberg_header(fp)读取文件,其中包含“fp中的行”;它会找到所需的行并中断。但是,next循环在break语句左边的位置取右。但是为什么呢?我认为这里有两个独立的迭代,都包含"for line in fp:",那么第二次迭代不应该从一开始就开始吗?
发布于 2017-08-17 19:22:15
不,不应该从头开始。打开的文件对象维护文件位置指示符,当您读取(或写入)该文件时,文件位置指示符将被移动。还可以通过文件的.seek方法移动位置指示符,并通过.tell方法查询位置指示符。
因此,如果您脱离了一个for line in fp:循环,您可以继续阅读另一个for line in fp:循环中断的地方。
顺便说一句,这种文件的行为并不是Python特有的:所有继承C的流和文件概念的现代语言都是这样工作的。
.seek和.tell方法在本教程中作了简要介绍。
有关Python中文件/流处理的更深入处理,请参见io模块的文档。该文档中有很多信息,其中一些信息主要是针对高级编码器的。你可能需要读几遍,写几个测试程序来吸收它说的话,所以当你第一次尝试阅读的时候,你可以随意浏览它。或者头几次。;)
发布于 2017-08-17 19:22:19
我认为这里有两个独立的迭代,都包含"for line in fp:",那么第二次迭代不应该从一开始就开始吗?
如果fp是一个列表,那么他们当然会。然而,它不是--它只是一个可迭代的。在本例中,它是一个类似文件的对象,具有seek、tell和read等方法。对于类似文件的对象,它们保持状态。当您从它们读取一行时,它会更改文件中读取指针的位置,因此下一次读取将在下面开始一行。
这通常用于跳过表格数据的头(至少在不使用csv.reader时)。
with open("/path/to/file") as f:
headers = next(f).strip() # first line
for line in f:
# iterate by-line for the rest of the file
...https://stackoverflow.com/questions/45743273
复制相似问题