我一直在尝试在Python中进行一些文本操作,并且遇到了很多问题,主要是由于对Python文件操作如何工作的基本误解,所以我希望能够清除它。
所以我想说我正在迭代一个名为“my.txt”的文本文件,它有以下内容:
3 10 7 8
2 9 8 3
4 1 4 2
我用来迭代文件的代码是:
file = open ("my.txt", 'r')
for line in file:
print line`
我从教程中复制并粘贴了上面的代码。我知道它的作用,但我不知道它为什么会起作用,这让我很烦。我试图准确理解变量“line”在文件中的含义。它是数据类型(字符串?)还是其他东西。我的直觉告诉我每一行代表一个字符串然后可以被操纵(这是我想要的)但我也理解字符串在Python中是不可变的。
记忆在这一切中扮演什么角色,如果我的文件太大而无法融入内存,它还能运作吗?第[3]行允许我访问每行中的第四个元素吗? 如果我只想在第二行工作,我可以这样做:
if line == 2:
for循环中的?
值得注意的是,我对Python很新,并且来自C \ C ++背景(不习惯不可变字符串)。我知道我把一些问题压成了一个问题,但对一般主题的任何澄清都会有所帮助:)
答案 0 :(得分:3)
line
是一行文字,表示为字符串。字符串是不可变的,但这不是操纵它们的问题; all variables in Python are references, and assigning to a variable points the reference to a new object。 (在C ++中,您无法更改引用所在的位置。)对文件进行迭代会在行上进行迭代,因此在每次迭代时,line
都会引用一个表示输入文件下一行的新字符串。
如果您熟悉range-based for loops或其他语言的每个结构,那就是Python for
的工作方式。循环变量不是计数器;你做不到
if line == 2:
因为line
不是该行的索引;这是线本身。你可以做到
for i, line in enumerate(f):
if i == 2:
do_stuff_with(line)
break # No need to load the rest of the file
请注意,file
是内置的名称,因此将该名称用于您自己的变量是一个坏主意。
答案 1 :(得分:1)
在Python中,您可以直接遍历文件。执行此操作的最佳方法是使用with
语句,如:
with open("myfile.txt") as f:
for i in f:
# do stuff to each line in the file
这些行是表示文件中每一行(由换行符分隔)的字符串。如果你只想在第二行操作,你可以这样做:
with open("myfile.txt") as f:
list_of_file = list(f)
second_line = list_of_file[2]
如果您想要访问第二行的一部分,可以按空格将其拆分为另一个列表,如下所示:
second_number_in_second_line = second_line.split()[1]
关于内存,直接遍历文件不将其全部读入内存,然而,将其转换为list
。如果您想在不这样做的情况下访问各个行,请使用itertools.islice
。
答案 2 :(得分:1)
在每次迭代中,line
变量都填充了从文件中读取的后续行的内容。所以,你将拥有:
第一次迭代中“3 10 7 8”
第二次迭代中的“2 9 8 3”
等
要单独获取数字,请使用拆分方法:link。
因此,将line
与2
进行比较并不会产生任何影响。如果您想识别行号,可以尝试:
lineNumber = 0
for line in file:
print line
if lineNumber == 2:
print "that was the second line!"
lineNumber += 1
根据评论中的建议,您可以使用enumerate:
来简化此操作for lineNumber, line in enumerate(file):
print line
if lineNumber == 2:
print "that was the second line!"
答案 3 :(得分:1)
假设您拥有相同的文件:
3 10 7 8\n
2 9 8 3\n
4 1 4 2\n
上有许多file object
在Python中,您可以按字符C样式读取文件:
with open('/tmp/test.txt', 'r') as fin: # fin is a 'file object'
while True:
ch=fin.read(1)
if not ch:
break
print ch, # comma suppresses the CR
您可以将整个文件作为单个字符串读取:
with open('/tmp/test.txt', 'r') as fin:
data=fin.read()
print data
作为枚举行:
with open('/tmp/test.txt', 'r') as fin:
for i, line in enumerate(fin):
print i, line
作为字符串列表:
with open('/tmp/test.txt', 'r') as fin:
data=fin.readlines()
循环文件对象的习惯用语:
for line in fin: # 'fin' is a file object result of open
print line
与:
同义for line in fin.readline():
print line
和类似:
for line in 'line 1\nline 2\nline 3'.splitlines():
print line
一旦习惯了循环于某些元素的Python样式循环(或Perl,或Obj C或Java范围样式循环),就可以使用它们而不必考虑它。
如果您想要每个项目的索引 - 请使用enumerate
答案 4 :(得分:0)
您可以使用您显示的代码迭代任意大小的文件,并且不应消耗超出最长单行大小的任何大量内存。
至于它是如何工作的,你可以深入研究Python本身的源代码,以了解血腥细节。在更高的层次上,只要考虑Python中的文件对象的实现者选择将逐行迭代作为其类的一个特性来实现。
Python中的许多集合数据类型和I / O接口都实现了某种形式的迭代。因此for
构造是Python中最常见的循环类型。您可以迭代列表,元组和集(按项),字符串(按字符),字典(按键),许多类(包括标准库中的那些类以及来自第三方的类)实现
“iterator (coding) protocol”以促进此类使用。