在Python3中按索引访问dict_keys元素


131

我正在尝试通过其索引访问dict_key的元素:

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

我想得到foo

与:

keys[0]
TypeError: 'dict_keys' object does not support indexing

我怎样才能做到这一点?


9
在py3.x中,dict.keys()返回类似于视图对象的集合,而不是列表(因此,无法建立索引)。使用keys = list(test)
Ashwini Chaudhary

当我执行list(something_dict)时,元组顺序是随机的:例如:list({'foo':'bar','hello':'world'})可以返回:list(foo,hello)或list(hello, foo),这为什么是随机的?
fj123x

7
字典没有任何顺序。(collections.OrderedDict如果需要有序钥匙,请使用)
Ashwini Chaudhary

关于线程安全的有趣讨论在此提出了解决该问题的各种方法: blog.labix.org/2008/06/27/…–
Paul

Answers:


161

list()而是调用字典:

keys = list(test)

在Python 3中,该dict.keys()方法返回一个字典视图对象,它作为一个集合。直接迭代字典也会产生键,因此将字典转换为列表会得到所有键的列表:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

3
当心Python 3中的list(dict.keys())-Labix Blog清楚地说明了问题所在,而没有提供解决方案。太好了!
Brandon Bradley

@BrandonBradley:一般而言:依靠某些动作是原子的反正不是一个好主意,因为Python是如此动态。您的代码可以轻松地传递给dict子类,例如,.keys()用Python代码处理的子类(例如可以进行线程切换)。
马丁·彼得

@BrandonBradley:感谢您的链接。在Python3中,只有该博客的评论之一中的解决方案对我有效:sorted(dict.keys())。在Python2中,dict.keys()将返回键值列表。
善意

2
@GoodWill:sorted(dict)会做完全一样的事情;按排序顺序生成键列表。list(dict)将按字典顺序列出您的列表。
马丁·彼得斯

1
或可以使用keys = [*test]
Alex78191 '19

59

不是完整的答案,但可能是有用的提示。如果它确实是您想要的第一项*,那么

next(iter(q))

比快得多

list(q)[0]

对于大词典,因为不必将整个内容存储在内存中。

对于10.000.000物品,我发现它快了将近40.000倍。

*如果dict只是Python 3.6之前的伪随机项目,则第一项(此后它在标准实现中已订购,尽管不建议依赖它)。


5
在Py3中,一切都变成迭代器,这一直是我最大的问题之一。它肯定更有效,但是有很多用例无缘无故变得“不干净”和复杂。例如,为什么他们不能只支持迭代器上的索引,而不必造成性能损失?
Ehsan Kia'9


0
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

将键附加到静态定义的列表然后对其进行索引的常规方式


2
没错,但是为什么不ls = list(test.keys())呢?我发现它更简单。
华伦天奴

是的,这样更有效。我写这个只是为了显示可读性。
pranav dua

0

在许多情况下,这可能是XY问题。为什么要按位置索引字典键?您真的需要吗?直到最近,字典甚至还没有在Python中排序,因此访问第一个元素是任意的。

我刚刚将一些Python 2代码翻译为Python 3:

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

这不是很漂亮,但也不是很糟糕。起初,我正要用可怕的东西代替它

    k = next(itertools.islice(iter(keys), i, None))

在我意识到这一切写成更好之前

for (k, res) in zip(d.keys(), some_list):

效果很好。

我相信在许多其他情况下,可以避免按位置索引字典关键字。尽管字典在Python 3.7中是有序的,但是依靠它并不是很漂亮。上面的代码仅起作用,因为的内容some_list是最近从的内容中产生的d

如果您确实需要disk_keys按索引访问元素,请仔细看一下代码。也许您不需要。


0

试试这个

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

结果看起来像这样。['foo','hello']

您可以在此处找到更多可能的解决方案。

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.