【问题标题】:Accessing dict_keys element by index in Python3在 Python3 中按索引访问 dict_keys 元素
【发布时间】:2013-09-04 07:26:53
【问题描述】:

我正在尝试通过索引访问 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

我该怎么做?

【问题讨论】:

  • 在 py3.x dict.keys() 中返回一个类似视图对象的集合,而不是列表(因此,无法进行索引)。使用keys = list(test)
  • 当我做 list(something_dict) 时,元组顺序是随机的:例如:list({'foo': 'bar', 'hello': 'world'}) 可以返回:list(foo , hello) 或 list(hello, foo),为什么这是随机的?
  • Dicts don't have any order.(如果您想要订购的钥匙,请使用collections.OrderedDict
  • 关于线程安全的有趣讨论在这里重新讨论解决此问题的各种方法:blog.labix.org/2008/06/27/…

标签: python dictionary python-3.x key


【解决方案1】:

Python 3

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']

另见detailed answer

【讨论】:

    【解决方案2】:

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

     key, val = next(iter(my_dict.items()))
    

    【讨论】:

      【解决方案3】:

      在许多情况下,这可能是XY Problem。为什么要按位置索引字典键?你真的需要吗?直到最近,在 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 元素,请仔细查看您的代码。也许你不需要。

      【讨论】:

        【解决方案4】:
        test = {'foo': 'bar', 'hello': 'world'}
        ls = []
        for key in test.keys():
            ls.append(key)
        print(ls[0])
        

        将键附加到静态定义的列表然后为相同的索引编制索引的常规方法

        【讨论】:

        • 没错,但为什么不是ls = list(test.keys())?我觉得它更简单。
        • 是的,这样更有效率。我写这个只是为了显示可读性。
        【解决方案5】:

        不是一个完整的答案,但也许是一个有用的提示。如果它真的是你想要的第一个项目*,那么

        next(iter(q))
        

        快很多
        list(q)[0]
        

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

        对于 10.000.000 个项目,我发现它的速度几乎快了 40.000 倍。

        *如果字典只是Python 3.6 之前的伪随机项,则第一项(之后在标准实现中排序,尽管不建议依赖它)。

        【讨论】:

        • 这一直是我在 Py3 中成为迭代器的最大问题之一。它肯定更有效,但是很多用例无缘无故变得“不干净”和复杂。例如,为什么它们不能只支持迭代器上的索引,而不必损失性能?
        • @EhsanKia 怎么能做到这一点。迭代器是专门使用的,因此不需要索引,您不能从集合中访问随机元素,这就是它具有性能优势的原因。
        • 对,我不是出于性能原因,只是出于可用性考虑。 q[N] 只是幕后list(q)[N] 的语法糖/简写,或者实际上更像是在它上面调用了 N 次 next(),所以它也适用于无限迭代器。现在,获取无限迭代器的第 5 个索引的最干净的方法是什么?我什至认为 itertools 对此没有任何解决方案。最好是next(itertools.islice(q, 5, None))
        • @EhsanKia 您刚刚编写了一个基于 itertools 的解决方案,并且可能是最好的 - 请参阅 itertools 中的 nth() 配方:docs.python.org/3/library/itertools.html#itertools-recipes。然而,这不是问题。语法糖不是很有用(可取的?),因为通过索引访问序列(列表)与以任何方式访问可迭代对象本质上是不同的——第一个可以无限重复,但第二个不能,因为它消耗可迭代的。
        【解决方案6】:

        改为在字典上调用list()

        keys = list(test)
        

        在 Python 3 中,dict.keys() 方法返回一个 dictionary view object,它充当一个集合。直接遍历字典也会产生键,因此将字典转换为列表会产生所有键的列表:

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

        【讨论】:

        • Watch out for list(dict.keys()) in Python 3 - Labix Blog 清楚地解释了问题所在,但没有提供解决方案。这太棒了!
        • @BrandonBradley:一般来说:依赖某些原子动作无论如何都是一个坏主意,因为 Python 是如此高度动态。您的代码可以很容易地传递一个 dict 子类,例如,.keys() 是在 Python 代码中处理的(例如,可以进行线程切换)。
        • @BrandonBradley:感谢您的链接。只有该博客的其中一个 cmets 的解决方案在 Python3 中对我有用:sorted(dict.keys())。在 Python2 中,dict.keys() 将返回一个键值列表。
        • @GoodWill: sorted(dict) 会做同样的事情;按排序顺序生成键列表。 list(dict) 将按字典顺序为您提供列表。
        • 或者可以使用keys = [*test]
        猜你喜欢
        • 1970-01-01
        • 2017-04-23
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2019-07-28
        • 1970-01-01
        • 2011-02-24
        相关资源
        最近更新 更多