如何在 Python 中复制一个字典
本教程讨论了如何在 Python 中复制一个字典。
我们将用两种方式演示如何复制一个字典:通过值传递和通过引用传递。
在 Python 中复制一个字典:通过引用传递
在 Python 中,对象不是隐式复制的。如果我们尝试将 food
复制到一个新的变量 meal
中,food
的值将被复制到 meal
中,但 food
的引用也将被复制。
meal = food
将一个对象直接等价于另一个对象将使新对象指向前一个对象;这意味着两个变量将引用同一个唯一的对象。
如果我们将 meal
中的 Fruit
值更新为 Banana
,food
中的 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
的值,它仍然会被替换;这是因为我们用来复制 food
到 meal
的方法是通过引用传递的。
在 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()
的问题是它们只对正在使用的对象进行浅层复制;如果你的字典有复杂的嵌套结构,这将是一个问题。
浅层复制只会复制它看到的内存中的第一层,因为嵌套对象会占用新的空间。
让我们把原来的对象改成一个嵌套的字典。
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'}}
原始版本和复制版本都更新了 Numbers
和 Address.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()
函数。
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