构建dict()时为何触发TypeError错误?
嗨,我来帮你捋清楚这个问题!
首先,先解释你遇到的TypeError:这个错误的核心原因是,当你用dict(a=k["a"], **k["b"])这种写法时,如果k["b"]这个字典里本身就包含了键"a",那么**k["b"]会把这个键值对展开成关键字参数传递给dict(),这就和你显式写的a=k["a"]重复了——相当于你给dict()传了两次a参数,一次是显式的,一次是展开字典带来的,Python不允许同一个关键字参数被传递多次,所以就触发了这个报错。
哦对了,虽然你给出的示例数据里k["b"]没有"a"键,但报错信息说明你的实际代码中,某个元素的b字典里肯定存在"a"这个键,才会导致冲突~
接下来,咱们说说怎么正确实现你的需求:
方法1:用字典解包的顺序避免冲突(推荐)
把要添加的"a": k["a"]放在字典解包的后面,这样即使k["b"]里有"a"键,后面的赋值也会覆盖前面的,而且不会触发报错:
d = [ { "a": 1, "b": { "x": 3 }, "blah": 4 }, { "a": 10, "b": { "x": 30 }, "blah": 40 }, ] x = [ {**k["b"], "a": k["a"]} for k in d ] print(x)
输出结果:
[{'x': 3, 'a': 1}, {'x': 30, 'a': 10}]
方法2:先复制字典再更新(更直观)
如果你觉得字典解包的写法有点绕,也可以先复制k["b"]的内容,再添加"a"的值,这样还能避免修改原字典(如果你不想改动原数据的话):
d = [ { "a": 1, "b": { "x": 3 }, "blah": 4 }, { "a": 10, "b": { "x": 30 }, "blah": 40 }, ] x = [] for k in d: new_dict = k["b"].copy() # 复制原b字典,避免修改原数据 new_dict["a"] = k["a"] x.append(new_dict) print(x)
这个方法的输出和上面完全一致。
顺便说下你之前update()方法的问题
你之前用[k["b"].update({"a": k["a"]}) for k in d]得到[None, None],是因为dict.update()是原地修改字典的方法,它不会返回修改后的字典,默认返回None。所以列表推导式收集的是每个update()的返回值,自然都是None啦。如果想用update()实现需求,得改成刚才方法2那样,先复制再更新,然后把更新后的字典添加到列表里。
内容的提问来源于stack exchange,提问作者WoJ

