如何在一行代码中复制并修改字典

95 投票
11 回答
36797 浏览
提问于 2025-04-16 15:07

我经常需要创建一些字典,它们之间只差一两个项目。以下是我通常的做法:

setup1 = {'param1': val1, 
            'param2': val2,
            'param3': val3,
            'param4': val4,
            'paramN': valN}

setup2 = copy.deepcopy(dict(setup1))
setup2.update({'param1': val10, 
                   'param2': val20})

程序中有一个时刻,setup2setup1 的完全复制,这让我有点紧张,因为我担心在程序运行的某个阶段,这两行代码可能会分开,这样就容易出现很多错误。

理想情况下,我希望能用一行代码完成这个操作(类似这样):

setup2 = dict(setup1).merge({'param1': val10, 
                        'param2': val20})

当然,我可以用分号把两个命令挤在一行里,但我觉得这样看起来很难看。还有其他选择吗?

11 个回答

20

解决方案

为此创建一个函数。

这样在代码中使用时,意图会更清晰,而且你可以在一个地方处理复杂的决策(比如深拷贝和浅拷贝的选择)。

def copy_dict(source_dict, diffs):
    """Returns a copy of source_dict, updated with the new key-value
       pairs in diffs."""
    result=dict(source_dict) # Shallow copy, see addendum below
    result.update(diffs)
    return result

现在这个拷贝是原子的,假设没有线程参与:

setup2=copy_dict(setup1, {'param1': val10, 'param2': val20})

补充 - 深拷贝

对于基本数据类型(比如整数和字符串),其实不需要做深拷贝:

>>> d1={1:'s', 2:'g', 3:'c'}
>>> d2=dict(d1)
>>> d1[1]='a'
>>> d1
{1: 'a', 2: 'g', 3: 'c'}
>>> d2
{1: 's', 2: 'g', 3: 'c'}

如果你确实需要深拷贝,可以使用 copy 模块:

result=copy.deepcopy(source_dict) # Deep copy

而不是:

result=dict(setup1)               # Shallow copy

确保你字典里的所有对象都支持深拷贝(任何可以被 pickled 的对象都可以)。

55

你可以在字典构造函数中使用关键字参数来进行更新。

new = dict(old, a=1, b=2, c=3)

# You can also unpack your modifications
new = dict(old, **mods)

这和下面的写法是一样的:

new = old.copy()
new.update({"a": 1, "b": 2, "c": 3})

来源

注意事项

  • dict.copy() 创建的是一个浅拷贝
  • 所有的键必须是字符串,因为它们是作为关键字参数传递的。
134

在我看来,最简单的方法就是这样:

new_dict = {**old_dict, 'changed_val': value, **other_new_vals_as_dict}

撰写回答