Como fundir dois dicionários em Python 2 e 3

  1. Python 2.7 Fundir Dicionário
  2. Python 3.5 (e superior) Dicionário Método Merge
  3. Conclusão da fusão de métodos

Suponha que temos dois dicionários A e B a serem fundidos, onde os valores em B irão substituir esses valores em A se eles compartilharem a mesma chave.

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

O objeto dictionary Python tem um método instrínseco update() método para atualizar o dicionário A com B,

A.update(B)

Mas os dados de A serão substituídos no local em vez de devolver um novo dicionário contendo a fusão de A e B.

Vamos introduzir os métodos de como fundir dois dicionários e devolver um novo dicionário.

Python 2.7 Fundir Dicionário

Método de compreensão de dicionário - 1

C = {key: value for d in (A, B) for key, value in d.items()}

d.itmes() retorna uma lista de (key, value) pares como 2-tubos de dicionário d.

Este método utiliza a compreensão aninhada do dicionário para fundir dois dicionários. A ordem correta de for deve ser dada uma atenção extra. Deve ser,

flattern_patterns = [planet
                    for sublist in planets
                    for planet in sublist]

Método de compreensão de dicionário - 2

Poderíamos também utilizar o método dict() para inicializar o novo dicionário.

C = dict((key, value) for d in (A, B) for key, value in d.items())

Tecnicamente falando, é quase o mesmo que o método acima, mas difere no desempenho que será mencionado posteriormente.

itertools.chain Método

O módulo itertools padroniza um array central de blocos de construção de iterator. Ele possui características como rapidez e eficiência de memória.

O itertools.chain retorna um objeto chain cujo método .next() retorna elementos desde o primeiro iterável até que ele se esgote, depois o(s) próximo(s) iterável(eis), até que todos se esgotem.

dict(itertools.chain(A.iteritems(), B.iteritems()))

iteritems() retorna um iterador sobre os (key, value) itens do dicionário.

Portanto, os scripts acima irão retornar um dicionário contendo itens de A e B.

copy e update Método

Como mencionado no início, update() poderia fundir A e B, mas irá substituir o dicionário no lugar. Poderíamos utilizar o método copy() para fazer uma cópia do dicionário A.

m = A.copy()
C = m.update(B)

Análise e comparação de performance dos métodos de fusão

import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict(itertools.chain(A.iteritems(), B.iteritems()))
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

Resultado:

0.0162378
0.029774
0.019975
0.0110059
Método Desempenho Posição
{key: value for d in (A, B) for key, value in d.items()} 0.0162378 2
dict((key, value) for d in (A, B) for key, value in d.items()) 0.029774 4
dict(itertools.chain(A.iteritems(), B.iteritems())) 0.019975 3
merge_dicts(a, b) 0.0110059 1

Python 3.5 (e superior) Dicionário Método Merge

A partir do Python 3.5, além dos mesmos métodos do Python 2.7, também tem ** operador de desempacotamento do dictionary, como introduzido em PEP-448. Ele permite descompactar um número arbitrário de itens.

Atenção

d.iteritems() torna-se depreciado em Python 3. Veja PEP-469

>>> C = {**A, **B}
>>> C
{'x': 10, 'y': 30, 'z': 40}
import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{**A, **B}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict(itertools.chain(A.items(), B.items()))
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
0.0017047999999999508
0.009127499999999955
0.0168952
0.01078009999999996
0.005767999999999995
Método Desempenho Posição
{**A, **B} 0.0017047999999999508 1
{key: value for d in (A, B) for key, value in d.items()} 0.009127499999999955 3
dict((key, value) for d in (A, B) for key, value in d.items()) 0.0168952 5
dict(itertools.chain(A.items(), B.items())) 0.01078009999999996 4
merge_dicts(a, b) 0.005767999999999995 2

Conclusão da fusão de métodos

Em Python 2.7, copy e update é o melhor método.

m = A.copy()
C = m.update(B)

Em Python 3.5+, o método de desempacotamento do dicionário é o melhor.

{**A, **B}

Artigo relacionado - Python Dictionary

  • Pretty Imprimir um Dicionário Bonito em Python
  • Copiar um Dicionário em Python