Python- 如何更新遍历文件行的 for 循环的索引?

Python- How do I update an index of a for loop that iterates over lines in a file?

我使用 for 循环遍历文件中的行。给定这一行:

line= [ ‘641', '"Tornadus', ' (Incarnate Form)"', '"Flying"', '""', '5', '"TRUE"']

我需要将索引 [6] 从“"TRUE"”重新格式化为布尔值 True。

完整的预期输出:d={'Tornadus, (Incarnate Form)': (641, 'Flying', None, 5, True}

我用过:

if "T" in line[6]:  # format legendary if TRUE
    line[6] = True

但是我得到这个错误:

Traceback (most recent call last): File "tester5p.py", line 305, in test_read_info_file_05 self.assertEqual(read_info_file(DATAFILE),info_db5())File "/Users/kgreenwo/Desktop/student.py", line 52, in read_info_file line[5] = False

TypeError: 'str' object does not support item assignment

如何在 for 循环中分配它?

查看我的完整代码:

def read_info_file(filename):
    f = open(filename, 'r')  # open file in read mode
    d = {}  # intitialze as empty
    count = 0  # helps to skip first line
    key = ""
    for line in f:  # get each line from file
        if count != 0:  # skip first line
        # 1___________________________________________open file,read, skip 1st line
            id_num = int(line[0])  # make id an integer
        # 2________________________________________________
            if ',' in line[1]:  # two parts to fullname, changes indexes
                part1 = line[1].strip('"')  # get format first part of name
                part2 = line[2].strip()  # get format second part of name
            # 3______________
                fullname = part1 + part2
                key = fullname
            # 4______________
                type1 = line[3].strip('"')
            # 5--------------
                if line[4] == "":  # check if there is not a second type
                    type2 = None  # correct format
                else:  # is a second type
                    type2 = line[4].strip('"')  # format second type
            # 6______________

                generation = line[5]  # format generation
            # 7_____________
                if "T" in line[6]:  # format legendary if TRUE
                    line[6] = True
                    legendary = line[6]
                else:  # format legendary if FALSE
                    line[6] = False
                    legendary = line[6]

            # 8______________________________________________one part to name
            else:  # one part to name
                fullname = line[1].strip('"')
            # 9______________
                type1 = line[2].strip('"')
            # 10_____________
                if line[3] == "":  # if no second type
                    type2 = None
                else:
                    type2 = line[3].strip('"')  # there is a second type
            # 11_____________
                generation = line[4]  # format generation
            # 12_____________
                if "T" in line[5]:  # format legendary if TRUE
                    line[5] = True
                    legendary = line[5]
                else:  # formmat Legendary if False
                    line[5] = False
                    legendary = line[5]

            value = (id_num, type1, type2, generation, legendary)
            d.update([(key, value)])
        count += 1
    return d

Reproducible example: input: (don't forget to skip first line!)

info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"

Output: d={'Bulbasaur':(1,'Grass','Poison',1,False)}

从你的例子中看不太清楚,但我的想法是:

for line in f:
    line = line.split(',')

现在你可以弄乱索引,看看你是否有更多的错误。 如果你使用:

if "T" in line[6]:  # format legendary if TRUE
    line[6] = True

它会起作用。

我没有重新分配它,而是这样做了并且成功了:

if "T" in line[6]:  # format legendary if TRUE
    legendary = True
else:  # format legendary if FALSE
    legendary = False

您的输入文件看起来像 comma-separated values 文件。如果是,你想要的就很简单了。

假设您的输入文件是这样的:

Input_file-43644346.txt

info_file1 = '''"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"

你可以这样做:

#!/usr/bin/env python3

import csv

input_file_name = "Input_file-43644346.txt"

with open(input_file_name, newline='') as input_file:
    next(input_file)        # skip first line
    record_extractor = csv.reader(input_file)
    d = {}
    for row in record_extractor:
        key = row[1].strip()
        row_truth = row[5] == "TRUE"        # simplifying the boolean retrieving
        # Using conditional expressions
        row_second_type = row[3].strip() if row[3] else None   
        output_row = (row[0], row[2], row_second_type, row[4], row_truth)
        d[key] = output_row

print("d=", d)

以下是此解决方案的一些要点:

  • 此示例采用 Python 3 的语法
  • 使用with确保及时关闭输入文件
  • 由于文件对象也是一个迭代器,您可以使用 next().
  • 跳过第一行
  • csv.reader() 会给你一个包含一行信息的元组。它会像您期望的那样处理带引号的字符串。
  • 表达式 row[5] == "TRUE" 将产生一个布尔表达式。您不需要使用 if 语句。
  • 空字符串等同于 False。任何其他字符串为真。
  • Conditional expressions 可用于将空字符串更改为您想要的 None
  • dict.update() 如果您已经有了字典或元组列表,您希望使用它的值来更新字典,但您最好使用 d[key] = value

但我的猜测是您的文件更像这样:

Input_file-43644346b.txt

"ID","Name","Type 1","Type 2","Generation","Legendary"
1,"Bulbasaur","Grass","Poison",1,"FALSE"
641,"Tornadus', ' (Incarnate Form)","Flying",,5,"TRUE"

然后您可以使用 csv.DictReader 读取您的数据:

#!/usr/bin/env python3

import csv

input_file_name = "Input_file-43644346b.txt"

with open(input_file_name, newline='') as input_file:
    record_extractor = csv.DictReader(input_file)
    d = {}
    for row in record_extractor:
        key = row["Name"].strip()
        row_truth = row["Legendary"] == "TRUE"
        row_second_type = row["Type 2"].strip() if row["Type 2"] else None
        output_row = (row["ID"], row["Type 1"],
                      row_second_type, row["Generation"], row_truth)
        d[key] = output_row

print("d=", d)

这使您能够使用 "column" 名称来标识每一行的不同部分


您可以使用 dictionary 理解来进一步简化您的代码:

#!/usr/bin/env python3

import csv

input_file_name = "Input_file-43644346.txt"

with open(input_file_name, newline='') as input_file:
    next(input_file)        # skip first line
    record_extractor = csv.reader(input_file)
    d = { row[1]: (row[0],
                   row[2],
                   row[3].strip() if row[3] else None,
                   row[4],
                   row[5] == "TRUE")
          for row in record_extractor }

print("d=", d)