Python 字典 .keys() 错误

42

我试着使用.keys()但是我得到的结果和以前一样并不是一个键的列表。相反,我得到了这个。

b = { 'video':0, 'music':23 }
k = b.keys()
print( k[0] )

>>>TypeError: 'dict_keys' object does not support indexing

print( k )
dict_keys(['music', 'video'])

除非我疯了,否则它应该只打印 ['music', 'video']。

发生了什么?


3
既然还没有人链接官方文档,那我来:字典视图对象 - Rik Poggi
请注意,字典是无序的,因此b.keys()[0]通常不是一个非常有用的操作。 - Lennart Regebro
5个回答

91

Python 3 改变了 dict.keys 的行为,现在它返回一个 dict_keys 对象,可迭代但不可索引(类似于旧的 dict.iterkeys,现在已经不存在了)。您可以使用显式调用 list 来获取 Python 2 中的结果:

>>> b = { 'video':0, 'music':23 }
>>> k = list(b.keys())
>>> k
['music', 'video']

或者只需

>>> list(b)
['music', 'video']

16
只需输入list(b)即可实现相同功能。 - Jochen Ritzel
我明白了,谢谢。那么你会如何遍历字典的键(dict_keys)呢? - tokageKitayama
3
@tokageKitayama: for x in b.keys() 或者只写成 for x in b。 意思是:如果想要遍历字典b的键(key),可以写成for x in b.keys(),也可以简写为for x in b - Fred Foo
除非您正在使用键视图的“set”类行为,否则请不要使用.keys()。字典本身支持迭代和包含其键的检查,而无需调用; 当您没有将其用于与原始dict不同的内容时,实际调用.keys()是浪费且不必要的冗长。 - ShadowRanger

8
如果您这样分配了k
k = list(b.keys())

您的代码将能够正常工作。

正如错误提示所说,dict_keys 类型不支持索引。


2
这是Python 2和3之间的一个重大变化。
在Python 2中:
>>> help(dict.keys)
keys(...)
    D.keys() -> list of D's keys

在Python 3中:

>>> help(dict.keys)
keys(...)
    D.keys() -> a set-like object providing a view on D's keys

这种行为的改变很有道理,因为字典在语义上是无序的,它的键是唯一的 - 就像集合一样。
这个改变意味着你不必每次想要用字典的键做某种集合比较时创建一个新的键列表。
为了帮助过渡到 Python 3,Python 2.7 还有另一个字典方法,`viewkeys`。`viewkeys` 方法最类似于 Python 3 的 `dict.keys` 方法:
>>> d
{'a': None, 'c': None, 'b': None, 'd': None}
>>> for k in d.viewkeys(): print k
... 
a
c
b
d
>>> d.viewkeys() & set('abc')
set(['a', 'c', 'b'])

在Python 3中,最接近旧行为的方法是将dict.keys()传递给list函数:
>>> d
{'d': None, 'a': None, 'c': None, 'b': None}
>>> list(d.keys())
['d', 'a', 'c', 'b']

或者直接将字典传递给list,因为字典本身会遍历其键:

>>> list(d)
['d', 'a', 'c', 'b']

您可以创建一个实用函数来抽象2和3之间的行为:
if hasattr(dict, 'viewkeys'): # Python 2.7
    def keys(d):
        return d.viewkeys()
else:  # Python 3
    def keys(d):
        return d.keys()

将字典传递给list以获取列表形式,在2和3中,您将获得相同的输出:

>>> d
{'b': None, 'a': None, 'c': None, 'd': None}
>>> keys(d)
dict_keys(['b', 'a', 'c', 'd'])
>>> list(d)
['b', 'a', 'c', 'd']

0
如果你只是想要从字典中获取键的列表,你可以直接这样做:
b = {"name": "xyz", "class":"abc", "college": "qwert"}  
key_list = list(b)

key_list 将包含所有键名的列表,不会重复键,如果出现多次,则仅计算一个副本。


-2
import random
b = { 'video':0, 'music':23,"picture":12 }
random.choice(tuple(b.items()))

# Returns a random dictionary entry as a tuple:
# ('music', 23)

你应该在回答中写更多细节(包括输入文本答案和解释,为什么某些东西会以这种方式工作),并直接使用更好的格式化代码(以保持 SO 的标准)。 - Tatranskymedved

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接