Search code examples
pythonpython-3.xpython-2.7dictionarymap-function

Python 3 map dictionary update method to a list of other dictionaries


In Python 2 I can do the following:

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> map(d.update, extras)
>> d['c']
>> 4

In Python 3 in get a KeyError:

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> map(d.update, extras)
>> d['c']
>> KeyError: 'c'

I would like to achieve the same behavior in Python 3 as in Python 2.

I understand that map in Python 3 will return an iterator (lazy evaluation and whatnot), which has to be iterated for the dictionary to be updated.

I had assumed the d['c'] key lookup would trigger the map iteration somehow, which is not the case.

Is there a pythonic way to achieve this behavior without writing a for loop, which I find to be verbose compared to map.

I have thought of using list comprehensions:

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> [x for x in map(d.update, extras)]
>> d['c']
>> 4

But it does not seem pythonic.


Solution

  • As you note, map in Python 3 creates an iterator, which doesn't (in and of itself) cause any updates to occur:

    >>> d = {'a': 1}
    >>> extras = [{'b':2}, {'c':4}]
    >>> map(d.update, extras)
    <map object at 0x105d73c18>
    >>> d
    {'a': 1}
    

    To force the map to be fully evaluated, you could pass it to list explicitly:

    >>> list(map(d.update, extras))
    [None, None]
    >>> d
    {'a': 1, 'b': 2, 'c': 4}
    

    However, as the relevant section of What's new in Python 3 puts it:

    Particularly tricky is map() invoked for the side effects of the function; the correct transformation is to use a regular for loop (since creating a list would just be wasteful).

    In your case, this would look like:

    for extra in extras:
        d.update(extra)
    

    which doesn't result in an unnecessary list of None.