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

Posted

技术标签:

【中文标题】TypeError:“dict_keys”对象不支持索引【英文标题】:TypeError: 'dict_keys' object does not support indexing 【发布时间】:2013-06-23 17:53:35 【问题描述】:
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

【问题讨论】:

好像是python3的错误 【参考方案1】:

很明显,您将d.keys() 传递给您的shuffle 函数。可能这是用 python2.x 编写的(当d.keys() 返回一个列表时)。在 python3.x 中,d.keys() 返回一个 dict_keys 对象,它的行为更像 set 而不是 list。因此,它无法被索引。

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

【讨论】:

。 . .或者只是list(d),它将为您提供 python2.x 和 python3.x 上的键列表,而无需制作任何副本 :-) 对于 python3,这是一个奇怪的重大变更设计决策。 您可能会这么认为,但我绝对认为这是正确的决定。 dict_keys 对象的行为更像是字典的一半键。具体来说,它们支持 O(1) 成员资格测试(以及其他可以在该事实之上有效实现的类似集合的方法)。这些事情是不可能用列表实现的,如果你想要一个字典键的列表,你总是可以简单地通过list(your_dictionary) 来获得它。 这有助于我看到python3要求我们用列表包装字典。 @Crt -- shuffle 是原始发布者代码中的函数名称(引发错误的函数)。查看代码,我认为它是从random.shuffle 在标准库中的实现中复制/粘贴的:-)【参考方案2】:

您将somedict.keys() 的结果传递给函数。在 Python 3 中,dict.keys 不返回一个列表,而是一个表示字典键视图的类集合对象,并且(像集合一样)不支持索引。

要解决此问题,请使用 list(somedict.keys()) 收集密钥并使用它。

【讨论】:

【参考方案3】:

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

next(iter(keys))

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

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

【讨论】:

OP 不想只想访问第一个项目或一次迭代这些项目,他们需要随机访问项目以随机播放它们。有了这些要求,将可迭代对象转换为列表正是正确的方法。此外,您的第二个 sn-p 可以替换为更清晰、更高效的for item in keys: pass【参考方案4】:

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

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

【讨论】:

【参考方案5】:

为什么在已经存在的情况下需要实现 shuffle?站在巨人的肩膀上。

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 的要求无关。 你是对的。看来他想实现自己的随机化器。 psah,也许他实际上并不知道他可以使用内置,但问题实际上似乎与类型错误有关。不过,我希望他转换并使用您的选项(除非它是非常具体的)来遵循基本的 DRY 和代码经济原则。

以上是关于TypeError:“dict_keys”对象不支持索引的主要内容,如果未能解决你的问题,请参考以下文章

如何更正错误“AttributeError: 'dict_keys' object has no attribute 'remove'”?

ValueError: (‘Unexpected parameters in params‘, dict_keys([‘cv‘]))

ValueError: (‘Unexpected parameters in params‘, dict_keys([‘cv‘]))

在 Python3 中按索引访问 dict_keys 元素

ValueError: ('Unrecognized keyword arguments:', dict_keys(['ragged'])) while loading keras model

为啥当我打印字典的键时,它前面有 dict_keys ? [复制]