Multiple assignments into a python dictionary

Question:

Is it possible to assign values to more than one keys of a dictionary in a more concise way than the one below?

I mean, let d be a dictionary initialized as below:

d={'a':1,'b':2,'c':3}

To assign values to multiple keys I need to do this:

d['a']=10
d['b']=200
d['c']=30

Can I achieve same with something like this:

d['a','b','c']=10,200,30

Thanks.

Asked By: ozi

||

Answers:

You can use dict.update:

d.update({'a': 10, 'b': 200, 'c': 30})

This will overwrite the values for existing keys and add new key-value-pairs for keys that do not already exist.

Answered By: Aamir Rind

You could use a dictionary comprehension e.g.

letters, nos = ['a','b','c'], [1,2,3]
d = {letters[i]: nos[i] for i in range(len(nos))}

output:

{‘a’: 1, ‘c’: 3, ‘b’: 2}

Answered By: ChrisProsser

You can always wrap it in a function:

def multiassign(d, keys, values):
    d.update(zip(keys, values))

Even if you didn’t know about update, you could write it like this:

def multiassign(d, keys, values):
    for k, v in zip(keys, values):
        d[k] = v

Or you can even write a dict subclass that gives you exactly the syntax you wanted:

class EasyDict(dict):
    def __getitem__(self, key):
        if isinstance(key, tuple):
            return [super().__getitem__(k) for k in key]
        else:
            return super().__getitem__(key)
    def __setitem__(self, key, value):
        if isinstance(key, tuple):
            self.update(zip(key, value))
        else:
            super().__setitem__(key, value)
    def __delitem__(self, key, value):
        if isinstance(key, tuple):
            for k in key: super().__delitem__(k)
        else:
            super().__setitem__(key, value)

Now:

>>> d = {'a': 1, 'd': 4}
>>> multiassign(d, ['a', 'b', 'c'], [10, 200, 300])
>>> d
{'a': 10, 'b': 200, 'c': 300, 'd': 4}
>>> d2 = EasyDict({'a': 1, 'd': 4})
>>> d2['a', 'b', 'c'] = 100, 200, 300
>>> d2
{'a': 10, 'b': 200, 'c': 300, 'd': 4}

Just be aware that it will obviously no longer be possible to use tuples as keys in an EasyDict.

Also, if you were going to use this for something serious, you’d probably want to improve the error handling. (d['a', 'b'] = 1 will give a cryptic message about zip argument #2 must support iteration, d['a', 'b', 'c'] = 1, 2 will silently work and do nothing to c, etc.)

Answered By: abarnert

You can also simply use the multiple assigment semantics:

d['a'], d['b'], d['c'] = 10, 200, 30
Answered By: Delgan

A speed comparison, from the worst to the best:

Python 3.5.3 |Continuum Analytics, Inc.| (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy.random as nprnd
   ...: d = dict([(_, nprnd.rand()) for _ in range(1000)])
   ...: values = nprnd.randint(1000, size=10000)
   ...: keys = nprnd.randint(1000, size=10000)
   ...: def multiassign(d, keys, values):
   ...:     for k, v in zip(keys, values):
   ...:         d[k] = v
   ...:
   ...: d1 = dict(d)
   ...: %timeit multiassign(d1, keys, values)
   ...: d1 = dict(d)
   ...: %timeit {**d1, **{keys[i]: values[i] for i in range(len(keys))}}
   ...: d1 = dict(d)
   ...: %timeit d1.update(zip(keys, values))
   ...: d1 = dict(d)
   ...: %timeit {*d1.items(), *zip(keys, values)}
   ...: d1 = dict(d)
   ...: %timeit {**d1, **{key: value for key, value in zip(keys, values)}}
   ...: d1 = dict(d)
   ...: %timeit {**d1, **dict(zip(keys, values))}
4 ms ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.66 ms ± 29.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.17 ms ± 31.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.81 ms ± 98.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.38 ms ± 75.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.96 ms ± 21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

So the clear winner is recreation of dictionary from dictionaries.

Answered By: Sklavit
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.