【问题标题】:How to return dictionary keys as a list in Python?如何在 Python 中将字典键作为列表返回?
【发布时间】:2013-05-25 00:40:40
【问题描述】:

Python 2.7 中,我可以将字典 keysvaluesitems 作为列表:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

现在,在 Python >= 3.3 中,我得到如下内容:

>>> newdict.keys()
dict_keys([1, 2, 3])

所以,我必须这样做才能得到一个列表:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

我想知道,有没有更好的方法在 Python 3 中返回一个列表?

【问题讨论】:

  • 关于这个主题的有趣线程安全问题在这里:blog.labix.org/2008/06/27/…
  • 我是 Python 新手,在我看来,这种无用的新数据类型的泛滥是 Python 最糟糕的方面之一。这个 dict_keys 数据类型有什么用?为什么不是列表?

标签: python python-3.x list dictionary python-2.x


【解决方案1】:

试试list(newdict.keys())

这会将dict_keys 对象转换为列表。

另一方面,你应该问问自己这是否重要。 Pythonic 的编码方式是假设鸭子类型(如果它看起来像一只鸭子并且它的叫声像一只鸭子,那么它就是一只鸭子)。在大多数情况下,dict_keys 对象就像一个列表。例如:

for key in newdict.keys():
  print(key)

显然,插入运算符可能不起作用,但无论如何这对于字典键列表没有多大意义。

【讨论】:

  • newdict.keys() 不支持索引
  • list(newdict) 也可以工作(至少在 python 3.4 中)。有什么理由使用.keys() 方法吗?
  • 注意:在调试器中pdb> list(newdict.keys()) 失败,因为它与 pdb 的同名命令冲突。使用pdb> !list(newdict.keys()) 转义pdb 命令。
  • @naught101 是的,.keys() 更清楚发生了什么。
  • 请注意,如果您使用 list(newdict.keys()) 由于散列顺序,键不在您放置它们的顺序!
【解决方案2】:

Python >= 3.5 替代方案:解压成列表文字 [*newdict]

Python 3.5 引入了新的unpacking generalizations (PEP 448),让您现在可以轻松做到:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

使用* 解包适用于可迭代的any 对象,并且由于字典在迭代时返回它们的键,因此您可以通过在列表文字中使用它来轻松创建列表。

添加.keys()[*newdict.keys()] 可能有助于使您的意图更加明确,尽管它会花费您一个函数查找和调用。 (老实说,这不是您应该真正担心的)。

*iterable 语法类似于 list(iterable),其行为最初记录在 Python 参考手册的 Calls section 中。在 PEP 448 中,对 *iterable 可能出现的位置的限制被放宽,允许它也被放置在列表、集合和元组文字中,Expression lists 的参考手册也更新了这一点。


虽然相当于list(newdict),但它的速度更快(至少对于小型字典而言),因为实际上没有执行任何函数调用:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

使用更大的字典,速度几乎相同(迭代大型集合的开销胜过函数调用的小成本)。


以类似的方式,您可以创建元组和字典键集:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

注意元组中的尾随逗号!

【讨论】:

  • 很好的解释,但请你参考任何描述这种“*newdict”类型语法的链接,我的意思是如何以及为什么返回字典中的键只是为了理解。谢谢
  • @MYounas 这种语法已经有很长一段时间了,即使在 Python 2 中也是如此。在函数调用中,您可以执行 def foo(*args): print(args) 后跟 foo(*{1:0, 2:0}) 并打印结果 (1, 2)。此行为在参考手册的Calls 部分中指定。带有 PEP 448 的 Python 3.5 刚刚放宽了对这些可能出现的位置的限制,允许现在使用 [*{1:0, 2:0}]。无论哪种方式,我都会编辑我的答案并包含这些内容。
  • *newdict - 这绝对是代码高尔夫球手的答案;P。另外:老实说,这不是你真正应该担心的事情 - 如果你是,不要使用 python
  • 今天学到了两件事:1.我可以将list(some_dict.keys())缩短为[*some_dict],2.表达“代码高尔夫球手”(以及2a。“代码高尔夫球手”的含义-谷歌搜索后)
  • 谢谢,这个答案真的很有用。
【解决方案3】:

list(newdict) 在 Python 2 和 Python 3 中都有效,提供了 newdict 中键的简单列表。 keys() 不是必需的。

【讨论】:

    【解决方案4】:

    您也可以使用列表推导

    >>> newdict = {1:0, 2:0, 3:0}
    >>> [k  for  k in  newdict.keys()]
    [1, 2, 3]
    

    或者,更短,

    >>> [k  for  k in  newdict]
    [1, 2, 3]
    

    注意:3.7 以下的版本不保证顺序(顺序仍然只是 CPython 3.6 的实现细节)。

    【讨论】:

    • 只需使用list(newdict)。这里不需要列表理解。
    【解决方案5】:

    “鸭子类型”定义有点偏离——dict.keys() 返回一个可迭代对象,而不是类似列表的对象。它可以在任何可迭代的地方工作——而不是列表可以工作的任何地方。列表也是可迭代的,但可迭代不是列表(或序列...)

    在实际用例中,对字典中的键做的最常见的事情是遍历它们,所以这是有道理的。如果您确实需要它们作为列表,您可以致电list()

    对于zip() 非常相似——在绝大多数情况下,它会被迭代——为什么要创建一个全新的元组列表来迭代它,然后再次将其丢弃?

    这是 python 使用更多迭代器(和生成器)而不是到处复制列表的大趋势的一部分。

    dict.keys() 应该与理解一起使用,但是 - 仔细检查拼写错误或其他东西......它对我来说很好:

    >>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
    >>> [key.split(", ") for key in d.keys()]
    [['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]
    

    【讨论】:

    • 你甚至不需要使用.keys();字典对象是自身可迭代的,并在迭代时产生键:[key.split(", ") for key in d].
    【解决方案6】:

    在不使用keys 方法的情况下转换为列表使其更具可读性:

    list(newdict)
    

    而且,在遍历字典时,不需要keys()

    for key in newdict:
        print key
    

    除非您在循环中修改它,这需要预先创建的键列表:

    for key in list(newdict):
        del newdict[key]
    

    在 Python 2 上,使用 keys() 会带来边际性能提升

    【讨论】:

      【解决方案7】:

      如果您需要单独存储密钥,这是一个使用Extended Iterable Unpacking (Python3.x+) 的解决方案,它比迄今为止提出的所有其他解决方案都需要更少的输入:

      newdict = {1: 0, 2: 0, 3: 0}
      *k, = newdict
      
      k
      # [1, 2, 3]
      

      Operation no. Of characters
      k = list(d) 9 characters (excluding whitespace)
      k = [*d] 6 characters
      *k, = d 5 characters

      【讨论】:

      • 我要指出的唯一小警告是k 始终是此处的列表。如果用户想要从键中获取元组或集合,他们将需要退回到其他选项。
      • 一个更值得注意的事实是,作为一个声明,*k, = d 对其可以出现的位置有限制(但请参阅并可能更新此答案,PEP 572 - 扩展解包是不支持赋值表达式 atm 可能有一天!)
      • 如果你想要列表的键和值怎么办?
      • @endolith 也许是keys, vals = zip(*d.items()) (尽管这给出了两个元组,足够接近)。我不知道还有比这更短的表达方式。
      【解决方案8】:

      我可以想到两种从字典中提取键的方法。

      方法一:- 使用 .keys() 方法获取密钥,然后将其转换为列表。

      some_dict = {1: 'one', 2: 'two', 3: 'three'}
      list_of_keys = list(some_dict.keys())
      print(list_of_keys)
      -->[1,2,3]
      

      方法二:- 创建一个空列表,然后通过循环将键附加到列表中。 您也可以使用此循环获取值(使用 .keys() 仅用于键,使用 .items() 用于键和值提取)

      list_of_keys = []
      list_of_values = []
      for key,val in some_dict.items():
          list_of_keys.append(key)
          list_of_values.append(val)
      
      print(list_of_keys)
      -->[1,2,3]
      
      print(list_of_values)
      -->['one','two','three']
      

      【讨论】:

        【解决方案9】:

        我知道这是一个非常古老的答案,但除了经典(可能更正确)的方法(some_dict.keys())之外,还有一种更“酷”且肯定更有趣的方法:

        some_dict = { "foo": "bar", "cool": "python!" }
        print( [*some_dict] == ["foo", "cool"] )         # True  
        

        注意:此解决方案不应在开发环境中使用;我在这里展示它只是因为我认为从*-operator-over-dictionary 的角度来看它很有趣。另外,我不确定这是否是已记录的功能,并且它的行为可能会在以后的版本中发生变化:)

        【讨论】:

          【解决方案10】:

          这是在一行代码中获取密钥列表的最佳方法

          dict_variable = {1:"a",2:"b",3:"c"}  
          [key_val for key_val in dict_variable.keys()]
          

          【讨论】:

          • 我想你的意思是[key_val for key_val in dict_variable.keys()]
          猜你喜欢
          • 2016-12-18
          • 2020-02-09
          • 2018-07-08
          • 1970-01-01
          • 1970-01-01
          • 2014-10-10
          • 2017-07-18
          相关资源
          最近更新 更多