61 votes

Pourquoi un dictionnaire peut-il être décompressé comme un tuple?

Aujourd'hui, j'ai vu une déclaration qui n'a pas fait exception. Quelqu'un peut-il expliquer la théorie derrière cela?

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

63voto

iCodez Points 41884

En Python, chaque objet iterable peut être décompressé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)
>>>

En outre, parce que de parcourir un dictionnaire renvoie uniquement les touches:

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

déballage d'un dictionnaire (qui itère sur elle) de même déballe seulement ses clés.


1en Fait, je dois dire que chaque objet iterable peuvent être installés en tant que noms de décompresser dans est égale à la longueur de l'objet 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
>>>

Mais c'est seulement le cas pour Python 2.x. En Python 3.x, vous avez étendu itérable déballage, ce qui vous permet de décompresser un objet iterable tout (fini) de taille en seulement les noms que vous avez besoin de:

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

20voto

Wooble Points 35620

Itérer un dict itère sur les touches. Puisque votre mot de passe a exactement deux clés, vous pouvez le décompresser en un tuple.

Ce n'est probablement pas une bonne pratique en général, car les dict sont non ordonnés et x == 'b' et y == 'a' seraient un résultat parfaitement légal de ce code.

8voto

Daniel Points 5467

quand vous parcourez un dictionnaire, vous obtenez ses clés

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

Décompresser n’est rien d’autre que parcourir l’objet et placer les éléments dans les variables données:

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

7voto

Paulo Bu Points 13991

Aucune science de fusée derrière elle. dict est un itérable, qui renvoie les clés à chaque itération. tuple() peut recevoir n'importe quel argument itérable (tant qu'il est fini), ainsi:

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

En voyant cela, il est facile d’en déduire que le déballage fonctionnera comme indiqué. De plus, tout itératif fini peut être décompressé:

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

5voto

Erik Allik Points 9158

Lorsque dans itérable contexte, les dicts sont traités comme une (non ordonnée) de la collection de clés, ce qui est ce que vous obtenez lorsque vous effectuez list(some_dict), ce qui est la même que l'appel à la keys() sur le dict:

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

Cependant, vous pouvez aussi faire plus.

Vous pouvez décompresser à la fois un dict's les deux clés et de valeurs si vous le mettez dans une liste de paires d'abord:

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

ou si vous voulez juste les paires

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

ou, disons, juste les touches:

>>> ((k1, _), (k2, _)) = d_pairs
>>> print k1, k2
a b

etc.

Mais bien sûr, depuis les dictionnaires - et je veux dire en général, et pas seulement en Python - contenir leurs articles dans une liste non-ordonnée de la, items() (en Python) est également de retour dans un apparemment arbitraire, et donc il n'y a aucun moyen de savoir quelle clé sera stockée dans la variable qui:

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

Comme vous le voyez, l'ordre des paires retourné par items() a été inversée par rapport à leur définition de l'ordre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X