Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can a dictionary be unpacked as a tuple?

People also ask

Can a dictionary be tuple?

Because tuples are hashable and lists are not, if we want to create a composite key to use in a dictionary we must use a tuple as the key. Write code to create a dictionary called 'd1', and in it give the tuple (1, 'a') a value of “tuple”.

Is unpacking possible in a tuple?

In python tuples can be unpacked using a function in function tuple is passed and in function, values are unpacked into a normal variable. The following code explains how to deal with an arbitrary number of arguments. “*_” is used to specify the arbitrary number of arguments in the tuple.

Why does Python think my dictionary is a tuple?

First, you ask why this is turned into a "tuple" - the answer to that question is because that is what the . items() method on dictionaries returns - a tuple of each key/value pair. Show activity on this post. With a dictionary you can add another variable while iterating over it.

Can you unpack a dictionary in Python?

Using the Unpack Operator ( ** ) to Unpack Dictionary in Python. The ** operator is used to pack and unpack dictionary in Python and is useful for sending them to a function.


In Python, every iterable can be unpacked1:

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

Moreover, because iterating over a dictionary returns only its keys:

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

unpacking a dictionary (which iterates over it) likewise unpacks only its keys.


1Actually, I should say that every iterable can be unpacked as long as the names to unpack into equals the length of the 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
>>>

But this is only the case for Python 2.x. In Python 3.x, you have extended iterable unpacking, which allows you to unpack an iterable of any (finite) size into just the names you need:

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

Iterating a dict iterates over the keys. Since your dict literal has exactly two keys, you can unpack it into a 2-tuple.

This is probably not a good practice in general, since (before python 3.7, or possibly earlier in some other implementations) dicts are unordered and x == 'b' and y == 'a' would be a perfectly legal outcome of that code.


when you iterate over a dictionary, you get its keys

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

Unpacking is nothing else than iterating over the object and put the elements in the given variables:

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

No rocket science behind it. dict is an iterable, which return the keys in each iteration. tuple() can receive any iterable as argument (as long as they are finite), so:

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

Seeing this, is easy to infer that unpacking will work as shown. Moreover, any finite iterable can be unpacked:

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

When in iterable context, dicts are treated as an (unordered) collection of keys, which is what you get when you do list(some_dict), which is the same as calling keys() on the dict:

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

However, you can also do more.

You can unpack both a dict's both keys and values if you turn it into a list of pairs first:

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

or if you just want the pairs

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

or, say, just the keys:

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

etc.

But of course since dictionaries — and I mean in general, not only in Python — contain their items in an un-ordered manner, items() (in Python) will also return them in a seemingly arbitrary order, and thus there is no way to know which key will be stored in which variable:

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

As you see, the order of the pairs returned by items() was reversed in comparison to their definition order.