使用 Python 在文件管理上进行 FOR 循环

FOR loop on File Management using Python

我正在做一个小练习。

There is a text file which has 3 columns: EmployeeID, First Name and Last Name. Write a program to create dictionary whose keys() are the EmployeeIDs in the text file and the values() are the first and last names combined.

我先试了没有循环。

f = open('empID.txt','r')
line1 = f.readline().split()
line2 = f.readline().split()
line3 = f.readline().split()
print line1
print line2
print line3
empdict={}
empdict[line1[0]] = line1[1]+" "+line1[2]
empdict[line2[0]] = line2[1]+" "+line2[2]
empdict[line3[0]] = line3[1]+" "+line3[2]
print "The resulting dictionary is \n",empdict
f.close()

这很好用。然后我尝试循环。

f = open('empID.txt','r')
empdict = {}
for line in f:
        line = f.readline().split()
        print line
        empdict[line[0]] = line[1]+" "+line[2]

print "The resulting dictionary is \n",empdict
f.close()

这引发了一个错误:

Traceback (most recent call last):
  File "empID3.py", line 4, in <module>
    line = f.readline().split()
ValueError: Mixing iteration and read methods would lose data

有人 advised 在类似情况下使用 while 循环代替,所以我尝试了:

代替 for line in f:,我添加了 while True:,这次它打印了所有 line 输出,然后抛出另一个错误而不是输出 dictionary

Traceback (most recent call last):
  File "empID3.py", line 6, in <module>
    empdict[line[0]]=line[1]+" "+line[2]
IndexError: list index out of range

有人可以帮我解决这个问题吗?我哪里错了?

您根本不需要使用 file.readline() 。遍历文件(迭代)已经为您提供了行,因此将现在冗余的调用完全删除 file.readline()

for line in f:
    print line
    line = line.split()
    empdict[line[0]] = line[1]+" "+line[2]

您也可以使用 while 循环,但是您需要检查结束条件;您的文件不是无穷无尽的。 file.readline() returns 读取整个文件后为空字符串;拆分一个空字符串会导致一个空列表,从而导致您的异常。

正在检查文件是否已完成的情况:

while True:
    line = f.readline()
    if not line:
        break
    line = line.split()
    print line
    empdict[line[0]] = line[1]+" "+line[2]

这比直接的 for 循环案例要冗长得多。

您可以将拆分限制为仅第一个 space:

empid, name = line.strip().split(None, 1)
empdict[empid] = name

str.split() call 在不使用参数或 None 时以白色 space 拆分,第二个参数限制拆分计数。如果姓氏包含 whitespace:

,这将特别有用
>>> line = '42 Guido van Rossum\n'
>>> line.split()
['42', 'Guido', 'van', 'Rossum']
>>> line.split(None, 1)
['42', 'Guido van Rossum\n']

尽管如此,您确实必须明确去除换行符。

你也可以使用 str.partition(),它比 str.split() 稍微快一点,因为你可以在一个固定的字符串上分割(而不是任意的白色space):

empid, _, name = line.strip().partition(' ')

_ 变量只是用来捕获分区;该方法 returns 3 个值。 _ 名称是约定俗成的,在此上下文中它意味着 我将忽略该值

可能是您文件中的某些行是空的;你会想跳过这些行,否则你仍然会得到 IndexErrorValueError 异常:

line = line.strip()
if not line:
    continue  # line is empty

最后但同样重要的是,如果您使用文件对象作为上下文管理器,在 with 语句中,Python 将在完成读取后为您关闭文件对象,无论您的代码是否成功或有异常:

empdict = {}
with open('empID.txt','r') as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        empid, _, name = line.partition(' ')
        empdict[empid] = name

现在根本不需要调用 f.close()

当你通过 for 循环时,解决方案可能会非常简单

output_dict = {}
for line in f:
    line = line.strip()
    key, value = line.split(" ", 1)
    output_dict[key] = value

或者,一个衬垫将是:

output_dict = dict(map(lambda i: i.strip().split(" ", 1), f.read().split("\n")))

PS:我更喜欢第一个而不是第二个,因为在我看来,它更干净。