如何在Python中将字典键作为列表返回?


777

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

>>> 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/…–
Paul

2
我是Python的新手,在我看来,这种无用的新数据类型的泛滥是Python最糟糕的方面之一。这个dict_keys数据类型有什么用?为什么不列出?
Phil Goetz

Answers:


974

尝试list(newdict.keys())

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

另一方面,您应该问自己是否重要。Python的编码方式是假设鸭子输入(如果它看起来像鸭子,而像鸭子一样嘎嘎叫,那就是鸭子)。在dict_keys大多数情况下,该对象的作用类似于列表。例如:

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

显然,插入运算符可能不起作用,但是对于字典关键字列表而言,这并没有多大意义。


49
newdict.keys()不支持索引
gypaetus

57
list(newdict)也有效(至少在python 3.4中)。是否有任何理由使用该.keys()方法?
naught101

46
注意:在调试器中pdb> list(newdict.keys()) 失败是因为它与同名的pdb命令冲突。使用pdb> !list(newdict.keys())逃脱PDB命令。
Riaz Rizvi

23
@ naught101是的,.keys()现在情况更清楚了。
Felix D.

2
请注意,如果您使用list(newdict.keys()),则由于哈希顺序,键的排列顺序将不正确!
Nate M

274

Python> = 3.5替代方法:解压缩为列表文字 [*newdict]

Python 3.5引入了新的拆包概括(PEP 448),使您现在可以轻松进行以下操作:

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

与解压缩的对象可*任何可迭代的对象一起使用,并且由于字典在迭代过程中会返回其键,因此您可以在列表文字中使用它轻松创建列表。

添加.keys()ie [*newdict.keys()]可能有助于使您的意图更加明确,尽管这将花费您函数查找和调用的费用。(实际上,这不是您真正应该担心的事情)。

*iterable语法类似于做list(iterable)其行为最初记录在呼叫部分 Python的参考手册。对于PEP 448,放宽了对*iterable可能出现的位置的限制,使其也可以放置在列表,集合和元组文字中,“ 表达式”列表上的参考手册也进行了更新以说明这一点。


尽管这等效于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”类型的语法中的任何链接,我的意思是如何以及为什么这将返回键从字典只是understanding.Thanx
穆罕默德·尤努斯·

1
@MYounas甚至在Python 2中,这种语法已经使用了相当长的时间。在函数调用中,您可以执行以下操作,def foo(*args): print(args)然后打印foo(*{1:0, 2:0})结果(1, 2)。此行为在参考手册的“ 呼叫”部分中指定。带有PEP 448的Python 3.5刚刚放宽了这些位置的限制,允许[*{1:0, 2:0}]立即使用。无论哪种方式,我都将编辑答案并包括在内。
Dimitris Fasarakis Hilliard '18

1
*newdict-这绝对是代码高尔夫球手的答案; P。另外:老实说,这不是您真正要担心的东西 -如果是,则不要使用python
Artemis仍然不相信

46

list(newdict)在Python 2和Python 3中均可使用,在中提供了键的简单列表newdictkeys()没必要 (:


26

在“鸭子类型”定义上有一点点偏离- 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']]

2
你甚至不需要使用.keys(); 字典对象本身是可迭代的,并且在迭代时产生密钥:[key.split(", ") for key in d]
马丁·彼得斯

25

您还可以使用列表推导

>>> 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的实现细节)。


6
只需使用list(newdict)。这里不需要列表理解。
马丁·彼得斯

8

不使用该keys方法转换为列表使其更具可读性:

list(newdict)

并且,当遍历字典时,不需要keys()

for key in newdict:
    print key

除非您要在循环中进行修改,否则将需要预先创建的键列表:

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

在Python 2上,使用会产生少量性能提升keys()


8

如果您需要单独存储密钥,那么此解决方案使用扩展的可迭代拆包(python3.x +),与迄今为止提供的所有其他解决方案相比,它的键入次数更少。

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

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
             k = list(d)      9 characters (excluding whitespace)   
            ├───────────────┼─────────────────────────────────────────┤
             k = [*d]         6 characters                          
            ├───────────────┼─────────────────────────────────────────┤
             *k, = d          5 characters                          
            ╘═══════════════╧═════════════════════════════════════════╛

1
我要指出的唯一小警告是,k这里始终是列表。如果用户想要元组或通过键进行设置,则需要退回到其他选项。
Dimitris Fasarakis Hilliard,

1
值得一提的是,事实上,*k, = d它的显示位置受到限制(但请查看PEP 572并可能对此答案进行更新-赋值表达式atm不支持扩展解包,但是可能有一天! )
Dimitris Fasarakis Hilliard,

如果您想同时列出键和值怎么办?
endlith

1
@endolith也许keys, vals = zip(*d.items())(尽管给出两个元组,但足够接近)。我不知道有比这短的表达。
cs95

1

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

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

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

方法2:- 创建一个空列表,然后通过循环将键附加到列表中。您也可以通过此循环获取值(仅将.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']
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.