Search code examples
pythonpython-2.7dictionaryiterable-unpacking

Why can a dictionary be unpacked as a tuple?


Today, I saw one statement which didn't throw an exception. Can anyone explain the theory behind it?

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

Solution

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