TypeError:“ dict_keys”对象不支持索引


144
def shuffle(self, x, random=None, int=int):
    """x, random=random.random -> shuffle list x in place; return None.

    Optional arg random is a 0-argument function returning a random
    float in [0.0, 1.0); by default, the standard random.random.
    """

    randbelow = self._randbelow
    for i in reversed(range(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = randbelow(i+1) if random is None else int(random() * (i+1))
        x[i], x[j] = x[j], x[i]

当我运行该shuffle函数时,它会引发以下错误,这是为什么呢?

TypeError: 'dict_keys' object does not support indexing

7
似乎是python3错误
DataEngineer

Answers:


231

显然,您正在传递d.keys()shuffle函数。可能是用python2.x编写的(d.keys()返回列表时)。使用python3.x,d.keys()返回一个dict_keys对象,其行为更像a而set不是alist。因此,无法对其进行索引。

解决方案是将list(d.keys())(或简单地list(d))传递给shuffle


22
。。。或者,list(d)这将为您提供python2.x和python3.x上的密钥列表,而不进行任何复制:-)
mgilson 2014年

11
对于python3来说,这是一个奇怪的突破性变更设计决策。
杰森

9
您可能会这样认为,但我绝对认为这是正确的决定。该dict_keys对象的行为更像是字典的键的一半。具体来说,它们支持O(1)成员资格测试(以及可以基于此事实有效实施的其他类似集合的方法)。列表不可能实现这些功能,并且如果您想要字典键的列表,那么您总是能够轻松地list(your_dictionary)获得它。
mgilson

这对我了解python3要求我们用list包装字典很有帮助。
DataEngineer

2
@Crt- shuffle是原始张贴者代码中的函数名称(引发错误的函数)。查看代码,我认为它是从random.shuffle标准库中的实现复制/粘贴的:-)
mgilson

11

您将把结果传递somedict.keys()给函数。在Python 3中,dict.keys它不返回列表,但是代表字典键视图的(类似于集合)的类似集合的对象不支持索引。

要解决此问题,请使用list(somedict.keys())来收集密钥并进行处理。


10

将迭代器转换为列表可能会产生成本。相反,要获得第一项,可以使用:

next(iter(keys))

或者,如果要遍历所有项目,则可以使用:

items = iter(keys)
while True:
    try:
        item = next(items)
    except StopIteration as e:
        pass # finish

1

为什么需要在已经存在的情况下实施改组?留在巨人的肩膀上。

import random

d1 = {0:'zero', 1:'one', 2:'two', 3:'three', 4:'four',
     5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine'}

keys = list(d1)
random.shuffle(keys)

d2 = {}
for key in keys: d2[key] = d1[key]

print(d1)
print(d2)

答案与一般知识有关,但没有解决OP的要求。
罗卡蒙德

你是对的。看来他想实现自己的随机器。
FooBar167

1
psah,也许他实际上并不知道他可以使用内置函数,但是问题实际上似乎与类型错误有关。尽管如此,我还是希望他切换并使用您的选择(除非是非常具体的内容)以遵循基本的DRY和代码经济原则。
罗卡蒙德

1

在Python 2中,dict.keys()返回一个列表,而在Python 3中,它返回一个生成器。

您只能遍历其值,否则可能必须将其显式转换为列表,即将其传递给列表函数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.