python 嵌套字典类型错误:“NoneType”对象不可订阅

jw5wzhpr  于 2023-03-21  发布在  Python
关注(0)|答案(3)|浏览(204)

我有一个包含问题的字典。键是一个数字,值是另一个字典。下面是一个结构的例子:

questions = {
    2313: {"question": "How much is 2+2", "answers": ["3", "4", "2", "1"], "correct": 2},
    4122: {"question": "What is the capital of France?", "answers": ["Lion", "Marseille", "Paris", "Montpellier"],
           "correct": 3}
}

我需要从一个文本文件('questions.txt ')向字典中添加更多的问题,其中的问题如下所示:
0#美国的首都是哪里?#华盛顿特区#纽约#洛杉矶#底特律#1
打开文件后,我循环遍历所有问题并将它们添加到字典中。我使用了协议'chatlib'中的一个函数:

def split_data(data, expected_fields):

    splitted = data.split('#')
    if len(splitted) == expected_fields:
        return splitted
    else:
        return

所以,例如,当我在问题之前使用它时,它将返回一个列表,看起来像这样:
['0','美国的首都是什么?','华盛顿特区','纽约','洛杉矶','底特律','1']
我尝试了很多不同的方法来写主代码,

list_new_questions = open("questions.txt").read().split('\n')
    for question in list_new_questions:
        questionlist = chatlib.split_data(question, 7)
        key = int(questionlist[0])
        questions[key] = {"question": "", "answers": [], "correct": 0}
        questions[key]["question"] = questionlist[1]
        questions[key]["answers"] = [questionlist[2], questionlist[3], questionlist[4], questionlist[5]]
        questions[key]["correct"] = int(questionlist[6])

但每次它返回一个错误(TypeError:'NoneType'对象不是可下标的),并说int(questionlist[0])的值是None,但我不明白为什么。它怎么会是None?它应该是列表中第一个元素questionlist的int值,它总是一个数字。每次我打印int(questionlist[0])它总是打印一个数字,所以我不明白为什么它说它是None。

gjmwrych

gjmwrych1#

让我们看看错误消息:
TypeError:“NoneType”对象不可订阅
下标表示法是当你使用方括号时,像这样:X[Y]。在引发异常的行中,唯一发生异常的地方是questionlist[0]。您不能订阅或索引None,因为None[0]意味着什么?因此这告诉您questionlistNone
我们可以通过查看前一行来找出原因,
questionlist = chatlib.split_data(question, 7)
split_data返回什么?
return splitted,一个字符串列表,或者return,和return None一样。所以我们知道后者一定发生了,这意味着你遇到了一行意外的#
这可能是因为1)某个地方有一个错别字,因为2)文件中有一个空行,或者因为3)文件以一个换行符结束(由某些编辑器自动插入)。
下一个问题是,在这些情况下,你希望发生什么?如果你只是想忽略任何不匹配的行,Yash的解决方案将帮助你。
但我认为,虽然允许3肯定是好的,2可能是好的,为您的用例,以及,我不认为你应该只想继续像什么都没有错的情况下,1.如果有一个错字,我认为你希望你的程序抱怨大声...但也许与更有用的错误消息。
您可以在不修改split_data的情况下完成此操作。以下是一个可能的解决方案:

list_new_questions = open("questions.txt").read().split('\n')
    for question in list_new_questions:
        if question.strip() == '':
            # Ignore lines with only whitespace
            continue
        questionlist = chatlib.split_data(question, 7)
        if questionlist is None:
            # Not the right number of fields!
            raise Exception(f"Invalid question format: {question!r}")
        key, question, *answers, correct = questionlist
        questions[int(key)] = {"question": question, "answers": answers, "correct": int(correct)}
gg0vcinb

gg0vcinb2#

在第3行,如果len(splitted)不等于7,则函数chatlib.split_data(question, 7)可以返回None
因此,当没有至少7个字段时,questionlist等于None。然后在第4行中,您试图访问None的索引0。
一个简单的修复和重组将是这样的:

def split_data(data):
    # validate data here
    splitted = data.split("#")
    # validate splitted here if you need to
    return splitted

list_new_questions = open("questions.txt").read().split("\n")
for question in list_new_questions:
    questionlist = chatlib.split_data(question)
    # do your validation here
    if len(questionlist) == 7:
        # try except maybe if you are unsure about the data split you get
        key = int(questionlist[0])
        questions[key] = {
            "question": questionlist[1], 
            "answers": questionlist[2:6], 
            "correct": int(questionlist[6)
        }
    else: 
        print("Invalid question format")
8i9zcol2

8i9zcol23#

如果实际字段为!= expected_fields,则split_data函数可以返回None值。
你可以像下面这样做,如果你开始提供更多的答案,也可以解释。
这也消除了对split_data函数的需要,因为它可以作为循环的一部分来完成。

with open("questions.txt") as f:
    new_questions = f.readlines()

    for q in new_questions:
        q = q.split("#")
        if len(q) == 7:
            questions[int(q[0])] = {
                "question": q[1],
                "answers": q[2:-1],
                "correct": int(q[-1])}
        else:
            print(f"Invalid Data {q}")

如果你想提供多于或少于4个答案,你可以做一些像下面这样的事情,只假设id是第一个字段,问题是第二个,答案是最后一个

for q in new_questions:
    q = q.split("#")
    try:
        questions[int(q[0])] = {
            "question": q[1],
            "answers": q[2:-1],
            "correct": int(q[-1])}
    except IndexError:
        print(f"Invalid data {q}")

相关问题