Search code examples
pythondictionarygrammariterable

Update Python Dictionary with Tuple of Strings to set (key, value) fails


dict.update([other]) says

Update the dictionary with the key/value pairs from other, overwriting existing keys. Return None.

update() accepts either another dictionary object or an iterable of key/value pairs (as tuples or other iterables of length two). If keyword arguments are specified, the dictionary is then updated with those key/value pairs: d.update(red=1, blue=2).

But

>>> {}.update( ("key", "value") )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 3; 2 is required

So why does Python apparently try to use the first string of the tuple?


Solution

  • The argument needs to be an iterable of tuples (or other iterables of length two), e.g. a list

    >>> d = {}
    >>> d.update([("key", "value")])
    >>> d
    {'key': 'value'}
    

    or a tuple, however this fails:

    >>> d = {}
    >>> d.update((("key", "value")))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: dictionary update sequence element #0 has length 3; 2 is required
    

    The Python documentation on tuple again solves this mystery:

    Note that it is actually the comma which makes a tuple, not the parentheses. The parentheses are optional, except in the empty tuple case, or when they are needed to avoid syntactic ambiguity.

    I.e. (None) is not a tuple at all, but (None,) is:

    >>> type( (None,) )
    <class 'tuple'>
    

    So this works:

    >>> d = {}
    >>> d.update((("key", "value"),))
    >>> d
    {'key': 'value'}
    >>>
    

    You can't omit the parentheses because

    >>> d = {}
    >>> d.update(("key", "value"),)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: dictionary update sequence element #0 has length 3; 2 is required
    

    that would be said syntactic ambiguity (comma is function argument separator).