Dict update method should support iterables of multi-keys dicts

car = {“brand”: “Ford”,“model”: “Mustang”,“year”: 1964}
car.update([{‘y’: 3, ‘x’:67}, {‘z’: 0, ‘f’:89}])
car
{‘brand’: ‘Ford’, ‘model’: ‘Mustang’, ‘year’: 1964, ‘y’: ‘x’, ‘z’: ‘f’}

should be

{‘brand’: ‘Ford’, ‘model’: ‘Mustang’, ‘year’: 1964, ‘y’: '3, ‘x’:67, ‘z’: 0, ‘f’: 89}

Semantics: when the iterable items are dicts and not tuples, treat them as such.

It would seem to be fully backwards-compatible

dict.update already has to handle two distinct cases:

  1. mapping
  2. iterable of 2-element iterables

You are asking the second to be further split into

  1. iterable of dicts
  2. iterable of non-dict iterables

You can already accomplish what you want with a list of dicts by folding them into a single dict, either explicitly:

car.update({‘y’: 3, ‘x’:67} | {‘z’: 0, ‘f’:89})

or by using reduce:

from functools import reduce
from operator import or_


car.update(reduce(or_, [{‘y’: 3, ‘x’:67}, {‘z’: 0, ‘f’:89}]))

Hi Philippe, and welcome :slight_smile:

You show in your example that this change would not be backwards-compatible at all: changing the semantics of a currently-valid construct is the definition of a compatibility break. I’m afraid that’s going to make this proposal a very hard sell.

You can achieve this for yourself currently without too much fuss:

>>> car = {"brand": "Ford", "model": "Mustang", "year": 1964}
>>> for d in [{'y': 3, 'x': 67}, {'z': 0, 'f': 89}]]:
...     car.update(d)
... 
>>> car
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'y': 3, 'x': 67, 'z': 0, 'f': 89}

Edit: @chepner raised an excellent point that a list comprehension is the wrong tool to use here; example corrected.

3 Likes

Why suggest a list comprehension when a regular for loop would suffice?

for d in [{'y': 3, 'x':67}, {'z': 0, 'f':89}]:
    car.update(d)
2 Likes

Or by using the unpacking syntax (although this uses separate dictionaries rather than an iterable of them):

# Make a new dictionary and reassign it
car = {**car, **{'y': 3, 'x':67}, **{'z': 0, 'f':89}}
# Make a new dictionary only for the new entries, then update in-place
car.update({**{'y': 3, 'x':67}, **{'z': 0, 'f':89}})

(Or the for loop already suggested.)

You could also make the updating the reduction:

reduce(dict.__ior__, [{'y': 3, 'x': 67}, {'z': 0, 'f': 89}], car)