Copiar um Dicionário em Python

Rayven Esplanada 30 janeiro 2023
  1. Copiar um Dicionário em Python: Passagem por referência
  2. Copiar um Dicionário em Python: Passar por Valor
  3. Cópia rasa do Python Dictionary
Copiar um Dicionário em Python

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 dicionário Python - Passar 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.

Dicionário de cópia Python - Cópia Rápida

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.

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

Artigo relacionado - Python Dictionary