如何在 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