1

I have a list of dicts from which I need to extract, into a new list, some elements. It works fine for one element:

d = [
    {
        "a": 1,
        "b": {
            "x": 3
        },
        "blah": 4
    },
    {
        "a": 10,
        "b": {
            "x": 30
        },
        "blah": 40
    },
]

z = [k["b"] for k in d]
print(z)

This outputs [{'x': 3}, {'x': 30}] which is the extracted data.

I now realize that I also need to include in the extracted dict another element from the original one: a (and its value).

I thought I would just take the value if b and update() it with a pair:

y = [k["b"].update({"a": k["a"]}) for k in d]
print(y)

This will not work (returns [None, None]) as update() does not return the resulting dict. A previous question led me to build a dict() from the components:

x = [dict(a=k["a"], **k["b"]) for k in d]
print(x)

This crashes with

Traceback (most recent call last):
  File "C:/dev/config/scratches/scratch_21.py", line 24, in <module>
    x = [dict(a=k["a"], **k["b"]) for k in d]
  File "C:/dev/config/scratches/scratch_21.py", line 24, in <listcomp>
    x = [dict(a=k["a"], **k["b"]) for k in d]
TypeError: type object got multiple values for keyword argument 'a'

What does that mean? Specifically: what are the "multiple values" when there is only one for that key (an integer) ?

WoJ
  • 27,165
  • 48
  • 180
  • 345

1 Answers1

7

You are passing in multiple a keys to the dict() call; one as a keyword argument, the other in the ** expanded mapping:

>>> dict(a=41, **{'a': 82})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type object got multiple values for keyword argument 'a'

It doesn't really matter what object you are calling here, keyword arguments must be unique in any call.

You presumably are using the same dictionaries you called .update() on, so now all your k['b'] dictionaries have an a key as well. Re-build your d list and your code will work:

>>> [k["b"] for k in d]
[{'x': 3}, {'x': 30}]
>>> [dict(a=k["a"], **k["b"]) for k in d]
[{'a': 1, 'x': 3}, {'a': 10, 'x': 30}]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Ahhh, I understand. The successive trials have modified `k['b']` - it is true that I was testing all the above code one after the other. Indeed, commenting out the intermediates and leaving only the last one fixed the problem. Thanks! – WoJ May 31 '18 at 19:33