如何在 Python 中复制一个字典

Rayven Esplanada 2023年1月30日
  1. 在 Python 中复制一个字典:通过引用传递
  2. 在 Python 中复制一个字典:通过值传递
  3. Python 字典的浅层复制
如何在 Python 中复制一个字典

本教程讨论了如何在 Python 中复制一个字典。

我们将用两种方式演示如何复制一个字典:通过值传递和通过引用传递。

在 Python 中复制一个字典:通过引用传递

在 Python 中,对象不是隐式复制的。如果我们尝试将 food 复制到一个新的变量 meal 中,food 的值将被复制到 meal 中,但 food 的引用也将被复制。

meal = food

将一个对象直接等价于另一个对象将使新对象指向前一个对象;这意味着两个变量将引用同一个唯一的对象。

如果我们将 meal 中的 Fruit 值更新为 Bananafood 中的 Fruit 值也将被替换。

meal["Fruit"] = "Banana"
print(food)
print(meal)

输出:

{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}
{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}

如果我们尝试更新 meal 块中的一个键,情况也是一样。我们将用 Circle Fruit 替换键 Fruit,并在将其弹出字典之前复制其值。

meal["Circle Fruit"] = meal.pop("Fruit")
print(food)
print(meal)

输出:

{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}
{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}

即使我们没有直接修改 food 的值,它仍然会被替换;这是因为我们用来复制 foodmeal 的方法是通过引用传递的。

Python 复制字典 - 通过引用传递

在 Python 中复制一个字典:通过值传递

通过值传递意味着将在内存中创建一个实际的对象副本,而不是在复制一个对象时将副本指向原始对象。

如果我们想复制一个字典,避免引用原来的值,那么我们应该想办法在内存中实例化一个新的对象。在 Python 中,有几个函数支持这种方法:dict()copy()deepcopy()

dict() 函数实例化一个新的字典对象。如果你把一个现有的字典包在这个函数周围,就会创建一个新的对象实例。

对于这个方法,我们将使用字典 food 中的同一个例子。

meal = dict(food)

另一种通过值传递的方法是使用 copy() 命令,它做的事情和 dict() 一样:在内存中实例化一个新对象。不同的是 copy() 是集合对象的内置函数,包括字典。

meal = food.copy()

对于这两种情况,我们修改 Fruit 值,替换 Vegetable 键。

meal["Fruit"] = "Apple"
meal["Greens"] = meal.pop("Vegetable")
print(food)
print(meal)

输出:

{'Fruit': 'Orange', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'} # food (original)
{'Fruit': 'Apple', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Greens': 'Lettuce'} # meal (copy)

通过使用 dict()copy() 实例化一个新的对象 meal,我们避免了在 meal 更新时引用原对象并更新其值。

Python 字典的浅层复制

dict()copy() 的问题是它们只对正在使用的对象进行浅层复制;如果你的字典有复杂的嵌套结构,这将是一个问题。

浅层复制只会复制它看到的内存中的第一层,因为嵌套对象会占用新的空间。

Python 复制字典 - 浅层复制

让我们把原来的对象改成一个嵌套的字典。

info = {
    "Numbers": [1, 2, 3],
    "Resident Name": "Sherlock",
    "Address": {"Street": "Baker", "Number": "221B", "City": "Miami"},
}

让我们使用 copy()dict() 声明一个新的对象 info2,从 info 复制并改变嵌套字典中的一些值。

info2 = info.copy()  # or dict(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

输出:

{'Numbers': [1, 4, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

原始版本和复制版本都更新了 NumbersAddress.City 的新值。Resident Name 值只更新了 info2 块,因为我们只对对象进行了浅层复制。

在 Python 中使用 copy 模块进行深度复制

深度复制基本上解决了浅层复制的问题。在复制一个对象时,它会检查是否有嵌套对象,并在内存中递归地创建新的对象。

在 Python 中,我们可以通过模块 copy 来实现深度复制,它包含了浅层和深层复制操作和实用程序。

import copy

我们将使用模块中的 deepcopy() 函数来深度复制我们字典中的嵌套对象。我们将使用上面同样的例子 info 块。

info2 = copy.deepcopy(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)

输出:

{'Numbers': [1, 2, 3], 'Resident Name': 'Sherlock', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Miami'}}
{'Numbers': [1, 4, 3], 'Resident Name': 'Holmes', 'Address': {'Street': 'Baker', 'Number': '221B', 'City': 'Lexington'}}

现在,原始字典 info 保持不变,即使在 info2 中进行了多次修改,包括嵌套对象。

综上所述,在 Python 中复制字典的方法有很多,但输出的结果不会都一样。直接用 = 赋值一个字典,会通过引用传递,指向原来的对象。

dict()copy() 这样的浅层复制函数只能解决非嵌套字典的问题。
考虑到嵌套字典,复制字典的最好方法是使用 copy 模块提供的 deepcopy() 函数。

Rayven Esplanada avatar Rayven Esplanada avatar

Skilled in Python, Java, Spring Boot, AngularJS, and Agile Methodologies. Strong engineering professional with a passion for development and always seeking opportunities for personal and career growth. A Technical Writer writing about comprehensive how-to articles, environment set-ups, and technical walkthroughs. Specializes in writing Python, Java, Spring, and SQL articles.

LinkedIn

相关文章 - Python Dictionary