如何修复“TypeError”-“dict_keys”对象不可下标?

Bet*_*agy 5 python typeerror

我对 Python 完全陌生,我只是在练习和“复制”一些 github 代码。在这样做的过程中,我意识到我正在使用最新版本的Python,而视频中的人正在使用Python 2.7,因此他使用的代码与我的不兼容。请帮助我如何重写代码。

def add_friend(self,friend_id):
    check_req = requests.get('https://gift-f06e4.firebaseio.com/.json?orderBy="my_friend_id"&equalTo=' + friend_id)

    data = check_req.json()
    print(check_req.ok)
    print(check_req.json())
    if data == {}:
        self.root.ids['add_friend_screen'].ids['add_friend_label'].text = "Invalid friend ID"

    else:
        key = data.keys()[0]
        new_friend_id = data[key]['my_friend_id']
        print('New friend id is', new_friend_id)
Run Code Online (Sandbox Code Playgroud)

问题出现在这一行:

key = data.keys()[0]
Run Code Online (Sandbox Code Playgroud)

我知道这不是我在 Python 3 中编写这部分的方式,但我不知道如何让它工作。

Bet*_*agy 8

好吧,我刚刚让它工作了:key = data.keys()[0]我尝试了,而不是key = list(data.keys())[0],它似乎工作了。

仍然不确定这是否是正确的方法。我会接受任何建议、建议、帮助。多谢!


exh*_*uma 6

tl;dr:如果字典中只有一个元素,那么使用list(data.keys())[0]就完全没问题。如果您有多个元素,那么答案是:“这取决于......”(因为您将随机获得一个元素)。

编辑:Python 3.7 的其他细节:字典排序已变得确定性,这一事实已成为语言规范的一部分,因此您可以在 Python 中依赖它。早期版本的 Python可能已经是确定性的,但这是特定于实现的,而不是规范的一部分,因此您不应依赖于此。最后,虽然 Python 3.7+ 确实如此,但其他编程语言却不一定如此,因此您需要小心地养成这种习惯。


对于这个特定的用例,您将其转换为列表的解决方案对我来说似乎很好。

我只是想稍微离题一下为什么这是不可订阅的,这可能会导致您找到另一个不依赖于[0].

注:查看 HTTP GET 调用返回的 JSON 文档示例将有助于做出更明智的声明。我将继续进行一个明智的猜测:

从代码中,我可以有把握地说 GET 调用的结果是一个 JSON 文档,其中包含一个对象(换句话说: 和 包围的东西{}。调用该方法时,这会转换为 Python 字典.json()

Python 字典不保证键的顺序。因此,这两个实例被认为是相同的(即使顺序不同),您可以在 Python 控制台中尝试:

>>> a = {"a": 10, "b": 20}
>>> b = {"b": 20, "a": 10}
>>> a == b
True
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您使用的data.keys()[0]意思是:“给我字典的第一个键”。但由于无法保证顺序,因此要求“第一个”项目实际上没有意义。这就是为什么在 Python 3 中它不再是可订阅的。他们禁止它是为了防止代码中出现逻辑错误。

作为旁注,我应该说,自 Python 3.7 以来,Python 字典中的排序在某些条件下是稳定的,但您仍然不应该依赖这种行为。

如果您 100% 确定您使用的字典只有一个元素,那么转换为列表并获取第一个元素是完全安全的。next()如果字典中只有一个元素,则使用 @rdas 提到的另一种方法也可以。如果字典有多个元素,则不能保证每次调用都会为您提供相同的元素,您只会从中获得“任何一个”元素。

此外,如果您可以控制 JSON 结构,则可以决定是否要将项目作为字典或列表返回。后者将有保证的订购。

如果您可以使用示例 JSON 文档编辑您的问题,我可以提供更多信息。