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

今天,我看到一个没有抛出异议的声明。 任何人都可以解释它背后的理论?

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

在Python中,每个迭代器都可以解压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实际上,我应该说每个迭代器都可以解压缩,只要解压缩的名称等于迭代器的长度即可:

 >>> 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中,您已经扩展了可迭代的解包 ,这使您可以将任何(有限)大小的迭代解包为您需要的名称:

 >>> # 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) >>> 

迭代dict遍历键。 由于你的字典正好有两个键,所以你可以把它打包成一个2元组。

这可能不是一个很好的做法,因为字典是无序的, x == 'b'y == 'a'将是该代码的完全合法的结果。

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

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

拆箱只不过是遍历对象,并把元素放在给定的variables:

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

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

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

看到这一点,很容易推断,拆包将工作如图所示。 而且,任何有限迭代都可以解压缩:

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

当在迭代的上下文中,字典被视为一个(无序)键的集合,这就是当你做list(some_dict)时候得到的,和dict上的keys()

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

不过,你也可以做更多。

你可以解压缩一个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) 

或者说,只是关键:

 >>> ((k1, _), (k2, _)) = d_pairs >>> print k1, k2 ab 

等等

但是当然,自从词典 – 我的意思是,不仅在Python中,它们以无序的方式包含它们的项目,而items() (在Python中)也将以一个看起来任意的顺序返回它们,因此没有办法要知道哪个键将被存储在哪个variables中:

 >>> ((k1, v1), (k2, v2)) = {'bar': 3, 'foo': 5}.items() >>> print k1, v1, k2, v2 foo 5 bar 3 

正如你所看到的,由items()返回的对的顺序与它们的定义顺序相反。