为什么字典可以作为元组解压缩?

时间:2014-04-24 12:15:45

标签: python python-2.7 dictionary iterable-unpacking

今天,我看到一条没有引发异常的声明。任何人都可以解释它背后的理论吗?

>>> x, y = {'a': 2, 'b': 5}
>>> x
'a'
>>> y
'b'

5 个答案:

答案 0 :(得分:63)

在Python中,每个iterable都可以解包 1

>>> x,y,z = [1, 2, 3]  # A list
>>> x,y,z
(1, 2, 3)
>>> x,y,z = 1, 2, 3  # A tuple
>>> x,y,z
(1, 2, 3)
>>> x,y,z = {1:'a', 2:'b', 3:'c'}  # A dictionary
>>> x,y,z
(1, 2, 3)
>>> x,y,z = (a for a in (1, 2, 3))  # A generator
>>> x,y,z
(1, 2, 3)
>>>

此外,因为迭代字典只返回其键:

>>> for i in {1:'a', 2:'b', 3:'c'}:
...     print i
...
1
2
3
>>>

解压缩字典(迭代它)同样只解包其密钥。


1 实际上,我应该说每个iterable都可以解压缩,只要要解包的名称等于可迭代的长度:

>>> a,b,c = [1, 2, 3]  # Number of names == len(iterable)
>>>
>>> a,b = [1, 2, 3]  # Too few names
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>>
>>> a,b,c,d = [1, 2, 3]  # Too many names
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 3 values to unpack
>>>

但这只是Python 2.x的情况。在Python 3.x中,您有extended iterable unpacking,它允许您将任何(有限)大小的可迭代解包为您需要的名称:

>>> # Python 3.x interpreter
...
>>> a, *b, c = [1, 2, 3, 4]
>>> a, b, c
(1, [2, 3], 4)
>>>
>>> a, *b = [1, 2, 3, 4]
>>> a, b
(1, [2, 3, 4])
>>>
>>> *a, b, c = [1, 2, 3, 4]
>>> a, b, c
([1, 2], 3, 4)
>>>

答案 1 :(得分:20)

迭代dict迭代键。由于您的dict文字只有两个键,因此您可以将其解压缩为2元组。

这可能不是一般的好习惯,因为(在python 3.7之前,或者在其他一些实现中可能更早),dicts是无序的,x == 'b'y == 'a'将是完全合法的结果。代码。

答案 2 :(得分:8)

当你遍历字典时,你得到它的键

data = {'a': 2, 'b': 5}
for key in data:
    print key

解包只不过是迭代对象并将元素放在给定的变量中:

keys = tuple(data) # gives ('a', 'b')
x, y = ('a', 'b')

答案 3 :(得分:7)

背后没有火箭科学。 dict是一个可迭代的,它在每次迭代中返回键。 tuple()可以接收任何可迭代的参数(只要它们是有限的),所以:

>>>tuple({'a': 2, 'b': 5})
('a','b')

看到这一点,很容易推断解压缩工作如图所示。此外,任何 finite iterable都可以解压缩:

>>> i = iter(range(3))
>>> a,b,c = i
>>> a,b,c
(0, 1, 2)

答案 4 :(得分:5)

当在可迭代上下文中时,dicts被视为(无序)键集合,这是您在执行list(some_dict)时获得的,这与在dict上调用keys()相同:< / p>

>>> d = {'a': 3, 'b': 5}
>>> list(d)
['a', 'b']
>>> d.keys()
['a', 'b']

但是,你也可以做更多。

如果您将{{1>}的两个键分别打开,那么您可以先解压缩它们:

dict

或者如果你只想要成对

>>> d = {'a': 3, 'b': 5}
>>> d_pairs = d.items()
>>> print d_pairs
[('a', 3), ('b', 5)]
>>> ((k1, v1), (k2, v2)) = d_pairs
>>> print k1, v1, k2, v2
a 3 b 5

或者说,只是键:

>>> p1, p2 = d_pairs
>>> print p1, p2
('a', 3) ('b', 5)

但是,当然,因为字典 - 我的意思是一般而言,不仅仅是在Python中 - 以无序的方式包含它们的项目,>>> ((k1, _), (k2, _)) = d_pairs >>> print k1, k2 a b (在Python中)也将以看似任意的顺序返回它们,并且因此无法知道哪个密钥将存储在哪个变量中:

items()

如您所见,>>> ((k1, v1), (k2, v2)) = {'bar': 3, 'foo': 5}.items() >>> print k1, v1, k2, v2 foo 5 bar 3 返回的对的顺序与其定义顺序相反。