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

How to return dictionary keys as a list in Python?

在Python2.7中,我可以得到字典键、值或项作为列表:

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

现在,在python>=3.3中,我得到了如下的结果:

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

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

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

我想知道,有没有更好的方法返回python 3中的列表?


试试list(newdict.keys())

这将把dict_keys对象转换为一个列表。

另一方面,你应该问问自己这是否重要。Python式的编码方式是假设鸭子打字(如果它看起来像鸭子,而且像鸭子一样嘎嘎叫,那就是鸭子)。在大多数情况下,dict_keys对象将像一个列表。例如:

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

显然,插入操作符可能不起作用,但对于字典键列表来说,这没有多大意义。


python>=3.5可选:解包到一个列表文本[*newdict]

python 3.5引入了新的解包通用化(pep 448),现在您可以轻松地执行以下操作:

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

使用*解包可以处理任何可Iterable的对象,而且由于字典在遍历时返回它们的键,因此可以通过在列表文本中使用它轻松创建列表。

添加.keys(),即[*newdict.keys()],可能有助于使您的意图更加明确,尽管这会导致函数查找和调用的开销。(老实说,这不是你真正应该担心的事情)。

*iterable语法类似于list(iterable)语法,其行为最初记录在python参考手册的calls部分中。使用PEP 448,可以放宽对*iterable出现位置的限制,允许它也被放在列表、集合和元组文本中,表达式列表的参考手册也被更新以说明这一点。

尽管与list(newdict)相当,但不同之处在于它更快(至少对于小字典而言),因为实际上没有执行函数调用:

1
2
3
4
5
6
7
8
%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

对于较大的字典,速度几乎是相同的(遍历大型集合的开销比函数调用的成本小)。

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

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

注意元组中的尾随逗号!


list(newdict)同时在python 2和python 3中工作,提供了newdict中键的简单列表。不需要keys()。(:


稍微偏离一下"duck-typing"定义——dict.keys()返回一个不可重复的对象,而不是一个类似列表的对象。它可以在任何一个iTable可以工作的地方工作——而不是列表可以工作的地方。列表也可以是iterable,但iterable不是列表(或序列…)

在实际的用例中,使用dict中的键最常见的事情是对它们进行迭代,所以这是有意义的。如果你确实需要它们作为一个列表,你可以打电话给list()

zip()非常相似——在绝大多数情况下,它是迭代的——为什么创建一个完整的新的元组列表,只是迭代它,然后再丢弃它?

这是Python使用更多迭代器(和生成器)而不是各地列表副本的大趋势的一部分。

不过,dict.keys()应该理解——仔细检查是否有错别字或其他什么…它对我来说很好:

1
2
3
>>> 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']]

您还可以使用列表理解:

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

或者,更短,

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

注:3.7下的版本不保证订购(订购仍然只是CPython 3.6的一个实现细节)。


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

1
list(newdict)

而且,在查字典时,不需要使用keys()

1
2
for key in newdict:
    print key

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

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

在python 2上,使用keys()可以获得边际性能增益。


如果您需要单独存储密钥,这里有一个解决方案,它使用扩展的不可重复解包(python3.x+)比目前提供的所有其他解决方案都需要更少的类型。

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

k
# [1, 2, 3]
1
2
3
4
5
6
7
            ╒═══════════════╤═════════════════════════════════════════╕
            │ k = list(d)   │   9 characters (excluding whitespace)   │
            ├───────────────┼─────────────────────────────────────────┤
            │ k = [*d]      │   6 characters                          │
            ├───────────────┼─────────────────────────────────────────┤
            │ *k, = d       │   5 characters                          │
            ╘═══════════════╧═════════════════════════════════════════╛


除了本页所述的方法外,您还可以使用操作员模块中的itemgetter

1
2
3
>>> from operator import itemgetter
>>> list(map(itemgetter(0), dd.items()))
[1, 2, 3]


您还可以执行tuple(dict)set(dict)操作:

1
2
3
4
>>> list(set(newdict))
[1, 2, 3]
>>> list(tuple(newdict))
[1, 2, 3]