Copiar um Dicionário em Python
- Copiar um Dicionário em Python: Passagem por referência
- Copiar um Dicionário em Python: Passar por Valor
- Cópia rasa do Python Dictionary
Este tutorial discute como se pode copiar um dicionário em Python.
Vamos demonstrar como copiar um dicionário de duas maneiras: passando por valor e passando por referência.
Copiar um Dicionário em Python: Passagem por referência
Em Python, os objectos não são implicitamente copiados. Se tentarmos copiar food para uma nova variável meal, os valores de food serão copiados para meal, mas também o será a referência de food.
meal = food
A equiparação directa de um objecto a outro fará com que o novo objecto aponte para o anterior; isto significa que as duas variáveis farão referência ao mesmo objecto único.
Se actualizarmos o valor Fruit em meal para Banana, o valor de Fruit em food será também substituído.
meal["Fruit"] = "Banana"
print(food)
print(meal)
Resultado:
{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}
{'Fruit': 'Banana', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'}
O mesmo acontece se tentarmos actualizar uma chave no bloco meal. Substituiremos a chave Fruit por Circle Fruit e copiaremos o seu valor antes de o retirarmos do dicionário.
meal["Circle Fruit"] = meal.pop("Fruit")
print(food)
print(meal)
Resultado:
{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}
{'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Circle Fruit': 'Orange'}
O valor de food ainda será substituído mesmo que não o tenhamos modificado directamente; isto porque o método que utilizámos para copiar food para meal passa por referência.

Copiar um Dicionário em Python: Passar por Valor
Passar por valor significa que uma cópia real do objecto será criada na memória, em vez de apontar a cópia para o objecto original ao copiar um objecto.
Se quisermos copiar um dicionário e evitar a referência aos valores originais, então devemos encontrar uma forma de instanciar um novo objecto na memória. Em Python, existem algumas funções que apoiam esta abordagem: dict(), copy(), e deepcopy().
A função dict() instantia um novo objecto de dicionário. Se envolver um dicionário existente em torno desta função, será criada uma nova instância do objecto.
Para este método, vamos utilizar o mesmo exemplo do dicionário food.
meal = dict(food)
Outra forma de passar por valor é utilizando o comando copy(), que faz a mesma coisa que dict() faz: instanciar um novo objecto na memória. A diferença é que copy() é uma função integrada de objectos de colecção, incluindo dicionários.
meal = food.copy()
Para ambos os cenários, vamos modificar o valor Fruit e substituir a chave Vegetable:
meal["Fruit"] = "Apple"
meal["Greens"] = meal.pop("Vegetable")
print(food)
print(meal)
Resultado:
{'Fruit': 'Orange', 'Vegetable': 'Lettuce', 'Poultry': 'Chicken', 'Fish': 'Cod'} # food (original)
{'Fruit': 'Apple', 'Poultry': 'Chicken', 'Fish': 'Cod', 'Greens': 'Lettuce'} # meal (copy)
Ao instanciar um novo objecto meal utilizando dict() ou copy(), evitamos a referência ao objecto original e a actualização dos seus valores se a meal for actualizada.
Cópia rasa do Python Dictionary
O problema com dict() e copy() é que eles só aplicam uma cópia superficial ao objecto a ser utilizado; isto será um problema se o seu dicionário tiver uma estrutura aninhada complexa.
A cópia rasa apenas copiará a primeira camada na memória que vê porque os objectos aninhados ocupam novos espaços.

Vamos mudar o objecto original para um dicionário aninhado.
info = {
"Numbers": [1, 2, 3],
"Resident Name": "Sherlock",
"Address": {"Street": "Baker", "Number": "221B", "City": "Miami"},
}
Vamos declarar um novo objecto info2 utilizando copy() e dict() para copiar de info e alterar alguns valores no dicionário aninhado.
info2 = info.copy() # or dict(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)
Resultado:
{'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'}}
Os novos valores de Numbers e Address.City são actualizados tanto na versão original como na versão de cópia. O valor Resident Name apenas actualizou o bloco info2 porque só executámos uma cópia rasa no objecto.
Cópia profunda com o módulo copy em Python
A cópia profunda resolve essencialmente o problema da cópia superficial. Ao copiar um objecto, verifica a existência de objectos aninhados e cria recursivamente novos objectos na memória.
Em Python, podemos conseguir uma cópia profunda com o módulo copy, que contém operações e utilidades de cópia rasa e profunda.
import copy
Utilizaremos a função deepcopy() do módulo para copiar em profundidade os objectos aninhados dentro do nosso dicionário. Utilizaremos o mesmo exemplo do bloco info acima.
info2 = copy.deepcopy(info)
info2["Numbers"][1] = 4
info2["Resident Name"] = "Holmes"
info2["Address"]["City"] = "Lexington"
print(info)
print(info2)
Resultado:
{'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'}}
Agora, o dicionário original info permanece inalterado, mesmo com as múltiplas alterações no info2, incluindo os objectos aninhados.
Em resumo, há muitas maneiras de copiar um dicionário em Python, mas a saída não será a mesma para todos. A atribuição directa de um dicionário com = passa-o por referência, apontando para o objecto original.
Funções de cópia rasa como dict() e copy() resolverão esse problema apenas para dicionários não aninhados.
A melhor maneira de copiar um dicionário, considerando dicionários aninhados, é utilizar a função deepcopy() fornecida pelo módulo copy.
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