【问题标题】:FOR loop on File Management using Python使用 Python 进行文件管理的 FOR 循环
【发布时间】:2015-02-17 08:00:54
【问题描述】:

我正在做一个小练习。

有一个包含 3 列的文本文件:EmployeeID、First Name 和 姓。编写一个程序来创建字典,其keys() 是 文本文件中的 EmployeeID 和 values() 是第一个也是最后一个 名字组合在一起。

我先尝试不循环。

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

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

【问题讨论】:

    标签: python python-2.7 for-loop file-io while-loop


    【解决方案1】:

    您根本不需要使用file.readline()。循环遍历文件(迭代)已经为您提供了这些行,因此完全放弃对 file.readline() 的现在冗余调用:

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

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

    检查文件完成情况:

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

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

    您可以将拆分限制在第一个空格内:

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

    str.split() call 在不使用参数或None 时会在空白处拆分,第二个参数会限制拆分计数。如果姓氏包含空格,这将特别有用:

    >>> 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() 稍微快一点,因为您可以在固定字符串(而不是任意空格)上进行拆分:

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

    _ 变量只是用来捕获分区;该方法返回 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()

    【讨论】:

    • 感谢您的解释。我已经删除了我的答案。下次我会更小心的
    • @MartijnPieters 非常感谢您抽出宝贵的时间。我尝试了您建议的所有更改,特别是两个想法:[empid, name]split(None, 1) 的列表非常酷且有趣。但不幸的是,他们都给了我IndexErrorValueError: need more than 0 values to unpack。我很抱歉他们都没有工作。我确定我做错了什么。我会继续努力,如果得到它会告诉你。再次感谢。
    • @Anand:您仍在拆分空行。您可以使用if line.strip(): 明确测试。
    【解决方案2】:

    通过 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:我更喜欢第一个而不是第二个,因为我认为它更干净。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2023-03-27
      • 2022-10-16
      相关资源
      最近更新 更多