在Python3中通过索引访问dict_keys元素

在Python3中通过索引访问dict_keys元素,python,dictionary,python-3.x,key,Python,Dictionary,Python 3.x,Key,我试图通过索引访问dict_键的元素: 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

我试图通过索引访问dict_键的元素:

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
如何执行此操作?

调用字典上的
list()

keys = list(test)
在Python3中,
dict.keys()
方法返回一个作为集合的。直接迭代字典也会生成键,因此将字典转换为列表会生成所有键的列表:

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

这不是一个完整的答案,但可能是一个有用的提示。如果它真的是你想要的第一件物品*,那么

next(iter(q))
比以前快多了

list(q)[0]
对于大型dict,因为整个内容不必存储在内存中

对于10.000.000件物品,我发现速度快了近4万倍

*如果dict之前只是一个伪随机项,则第一项(之后在标准实现中进行排序,尽管不建议依赖它)


在许多情况下,将键附加到静态定义的列表中,然后为其编制索引的传统方法可能是一种错误。为什么要按位置索引字典键?你真的需要吗?直到最近,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):
这很好用

我相信在许多其他情况下,可以避免按位置索引字典键。尽管在Python3.7中对字典进行了排序,但依赖它并不好看。上面的代码之所以有效,是因为最近从
d
的内容生成了
some\u list
的内容

如果确实需要按索引访问
disk\u keys
元素,请仔细查看代码。也许你不需要。试试这个

keys = [next(iter(x.keys())) for x in test]
print(list(keys))
结果是这样的。 ['foo','hello']

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

我想要第一个字典项的“键”和“值”对。我使用了以下代码

 key, val = next(iter(my_dict.items()))
Python 3 输出

['a', 'b', 'c']
['one', 'two', 'three']

在py3.x
dict.keys()中也可以看到这一点。
返回一个类似于视图对象的集合,而不是列表(因此,索引是不可能的)。使用
keys=list(test)
当我做list(某物)时,元组顺序是随机的:例如:list({'foo':'bar','hello':'world')可以返回:list(foo,hello)或list(hello,foo),为什么是随机的?(如果你想要有序的键,请使用
collections.orderedict
)这里有关于线程安全的有趣讨论,讨论了解决这个问题的各种方法:在没有提供解决方案的情况下清楚地解释了问题所在。这太棒了@布兰登·布拉德利:一般来说:依赖于某些动作的原子性是一个坏主意,因为Python是高度动态的。您的代码可以很容易地传递一个
dict
子类,例如,其中
.keys()
是用Python代码处理的(例如,可以进行线程切换)。@BrandonBradley:谢谢您的链接。在Python3:sorted(dict.keys())中,只有来自该博客评论之一的解决方案对我有效。在Python2中,dict.keys()将返回键值列表。@GoodWill:
sorted(dict)
将执行完全相同的操作;按排序顺序生成键列表<代码>列表(dict)将按字典顺序为您提供列表。或者可以使用
键=[*test]
这一直是我最大的问题之一,因为在Py3中所有内容都成为迭代器。它肯定更高效,但是很多用例毫无理由地变得“不干净”和复杂。例如,为什么它们不能只支持迭代器上的索引,而不一定会有性能损失?@EhsanKia一个人如何才能做到这一点。迭代器是专门使用的,因此不需要索引,您无法从集合中访问随机元素,这就是为什么is具有性能优势。对,我不是出于性能原因,只是出于可用性。q[N]只是
list(q)[N]
幕后的语法糖/速记,或者更像是对其调用N次的next(),因此它也适用于无限迭代器。现在,获取无限迭代器第5个索引的最干净的方法是什么?我甚至不认为itertools有任何解决方案。最好是
next(itertools.islice(q,5,None))
这没有错,但为什么不
ls=list(test.keys())
?我觉得更简单。是的,这更有效。我写这篇文章只是为了显示可读性。
mydict = {'a': 'one', 'b': 'two', 'c': 'three'}
mykeys = [*mydict]          #list of keys
myvals = [*mydict.values()] #list of values

print(mykeys)
print(myvals)
['a', 'b', 'c']
['one', 'two', 'three']