Cómo combinar dos diccionarios en una sola expresión?


Tengo dos diccionarios Python, y quiero escribir una sola expresión que devuelva estos dos diccionarios, combinados. El método update() sería lo que necesito, si devolviera su resultado en lugar de modificar un dict in-place.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

¿Cómo puedo obtener ese dict final fusionado en z, no en x?

(Para ser extra-claro, el último-uno-gana el manejo de conflictos de dict.update() es lo que estoy buscando también.)

Author: wim, 2008-09-02

30 answers

¿Cómo puedo combinar dos diccionarios Python en una sola expresión?

Para los diccionarios x y y, z se convierte en un diccionario fusionado con valores de y reemplazando a los de x.

  • En Python 3.5 o superior,:

    z = {**x, **y}
    w = {'foo': 'bar', 'baz': 'qux', **y}  # merge a dict with literal values
    
  • En Python 2, (o 3.4 o inferior) escriba una función:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values
        z.update(y)    # modifies z with y's keys and values & returns None
        return z
    

    Y

    z = merge_two_dicts(x, y)
    

Explicación

Digamos que tienes dos dictados y quieres fusionarlos en un nuevo dictado sin alterar los dictados originales:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

El resultado deseado es obtener un nuevo diccionario (z) con los valores fusionados, y los valores del segundo diccionario sobrescribiendo los del primero.

>>> z
{'a': 1, 'b': 3, 'c': 4}

Una nueva sintaxis para esto, propuesta en PEP 448 y disponible a partir de Python 3.5 , es

z = {**x, **y}

Y de hecho es una sola expresión. Ahora se muestra como implementado en el programa de lanzamiento de para 3.5, PEP 478, y ahora ha hecho su camino hacia Qué hay de nuevo en el documento Python 3.5.

Sin embargo, dado que muchas organizaciones todavía están en Python 2, es posible que desee hacer esto de una manera compatible con versiones anteriores. El clásico Python el camino, disponible en Python 2 y Python 3.0-3.4, es hacer esto como un proceso de dos pasos:

z = x.copy()
z.update(y) # which returns None since it mutates z

En ambos enfoques, y vendrá en segundo lugar y sus valores reemplazarán los valores de x, por lo tanto 'b' apuntará a 3 en nuestro resultado final.

Todavía no en Python 3.5, pero quiere una única expresión

Si aún no está en Python 3.5, o necesita escribir código compatible con versiones anteriores, y desea esto en una única expresión , el enfoque más eficaz, aunque correcto, es ponerlo en una función:

def merge_two_dicts(x, y):
    """Given two dicts, merge them into a new dict as a shallow copy."""
    z = x.copy()
    z.update(y)
    return z

Y luego tienes una sola expresión:

z = merge_two_dicts(x, y)

También puede hacer una función para fusionar un número indefinido de dictados, de cero a un número muy grande:

def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

Esta función funcionará en Python 2 y 3 para todos los dictados. por ejemplo, dictos dados a a g:

z = merge_dicts(a, b, c, d, e, f, g) 

Y los pares de valores clave en g tendrán prioridad sobre los dictados a a f, y así sucesivamente.

Críticas de Otras respuestas

No uses lo que ves en la respuesta anteriormente aceptada:

z = dict(x.items() + y.items())

En Python 2, se crean dos listas en memoria para cada diccionario, se crea una tercera lista en memoria con una longitud igual a la longitud de las dos primeras juntas, y luego se descartan las tres listas para crear el diccionario. En Python 3, esto fallará porque estás agregando dos dict_items objetos juntos, no dos listas -

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

Y tendría que crearlas explícitamente como listas, por ejemplo, z = dict(list(x.items()) + list(y.items())). Esto es un desperdicio de recursos y poder de cómputo.

De manera similar, tomar la unión de items() en Python 3 (viewitems() en Python 2.7) también fallará cuando los valores sean objetos inutilizables (como las listas, por ejemplo). Incluso si sus valores son hashables, dado que los conjuntos están desordenados semánticamente, el el comportamiento no está definido con respecto a la precedencia. Así que no hagas esto:

>>> c = dict(a.items() | b.items())

Este ejemplo demuestra lo que sucede cuando los valores no se pueden lavar:

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Aquí hay un ejemplo donde y debe tener prioridad, pero en su lugar el valor de x se conserva debido al orden arbitrario de los conjuntos:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

Otro truco que no debes usar:

z = dict(x, **y)

Esto utiliza el constructor dict, y es muy rápido y eficiente en memoria (incluso un poco más que nuestros dos pasos proceso), pero a menos que sepa con precisión lo que está sucediendo aquí (es decir, el segundo dict se pasa como argumentos de palabras clave al constructor dict), es difícil de leer, no es el uso previsto, y por lo tanto no es Pitónico.

Aquí hay un ejemplo del uso que se está remediando en django.

Los dictados están destinados a tomar claves hashables (por ejemplo, frozensets o tuplas), pero este método falla en Python 3 cuando las claves no son cadena.

>>> c = dict(a, **b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

De la lista de correo , Guido van Rossum, el creador del lenguaje, escribió: {[60]]}

Estoy bien con declarando dict({}, **{1:3}) ilegal, ya que después de todo es abuso de mecanismo.

Y

Aparentemente dict (x, **y) está dando vueltas como "cool hack" para " call x. actualizar (y) y devolver x". Personalmente lo encuentro más despreciable que fresco.

Es mi entendimiento (así como como la comprensión del creador del lenguaje ) que el uso previsto para dict(**y) es para crear dictados con fines de legibilidad, por ejemplo:

dict(a=1, b=10, c=11)

En lugar de

{'a': 1, 'b': 10, 'c': 11}

Respuesta a los comentarios

A pesar de lo que dice Guido, dict(x, **y) está en línea con la especificación dict, que por cierto. funciona tanto para Python 2 y 3. El hecho de que esto solo funcione para las claves de cadena es una consecuencia directa de cómo funcionan los parámetros de las palabras clave y no dict. Tampoco es el uso del operador * * en este lugar un abuso del mecanismo, de hecho ** fue diseñado precisamente para pasar dictados como palabras clave.

De nuevo, no funciona para 3 cuando las teclas no son cadenas. El contrato de llamada implícito es que los espacios de nombres toman dictados ordinarios, mientras que los usuarios solo deben pasar argumentos de palabras clave que sean cadenas. Todos los demás callables lo hicieron cumplir. dict rompió esta consistencia en Python 2:

>>> foo(**{('a', 'b'): None})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() keywords must be strings
>>> dict(**{('a', 'b'): None})
{('a', 'b'): None}

Esta inconsistencia fue mala dadas otras implementaciones de Python (Pypy, Jython, IronPython). Por lo tanto, se arregló en Python 3, ya que este uso podría ser un cambio radical.

Sostengo que es incompetencia maliciosa escribir intencionalmente código que solo funciona en una versión de un lenguaje o que solo funciona dadas ciertas restricciones arbitrarias.

Otro comentario:

dict(x.items() + y.items()) sigue siendo la solución más legible para Python 2. La legibilidad cuenta.

Mi respuesta: merge_two_dicts(x, y) en realidad parece mucho más claro para mí, si realmente estamos preocupados por la legibilidad. Y no es compatible con forward, ya que Python 2 está cada vez más obsoleto.

Menos Performante Pero Correcto Ad-hocs

Estos enfoques son menos performantes, pero proporcionarán un comportamiento correcto. Serán mucho menos performant que copy y update o el nuevo desempaquetado porque iteran a través de cada par clave-valor en un nivel más alto de abstracción, pero hacen respetar el orden de precedencia (los últimos dictados tienen precedencia)

También puede encadenar los dictos manualmente dentro de una comprensión de dictos:

{k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7

O en python 2.6 (y tal vez ya en 2.4 cuando se introdujeron las expresiones generator):

dict((k, v) for d in dicts for k, v in d.items())

itertools.chain encadenará los iteradores sobre los pares clave-valor en el orden correcto:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

Análisis del rendimiento

Solo voy a hacer el análisis de rendimiento de los usos conocidos por comportarse correctamente.

import timeit

Lo siguiente se hace en Ubuntu 14.04

En Python 2.7 (system Python):

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(), y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

En Python 3.5 (deadsnakes PPA):

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

Recursos en Diccionarios

 3562
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-03 17:02:21

En tu caso, lo que puedes hacer es:

z = dict(x.items() + y.items())

Esto, como lo desee, pondrá el dict final en z, y hará que el valor de key b se anule correctamente por el valor del segundo dict (y):

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

Si usas Python 3, es solo un poco más complicado. Para crear z:

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
 1456
Author: Thomas Vander Stichele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-29 17:18:02

Una alternativa:

z = x.copy()
z.update(y)
 559
Author: Matthew Schinckel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-02 13:00:46

Otra opción, más concisa:

z = dict(x, **y)

Nota: esto se ha convertido en una respuesta popular, pero es importante señalar que si y tiene claves que no sean de cadena, el hecho de que esto funcione es un abuso de un detalle de implementación de CPython, y no funciona en Python 3, o en PyPy, IronPython, o Jython. Además, Guido no es un fan . Así que no puedo recomendar esta técnica para código portátil compatible con reenvío o implementación cruzada, lo que realmente significa que debería ser evitada por completo.

 278
Author: Carl Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-21 06:43:24

Esta probablemente no será una respuesta popular, pero es casi seguro que no quieres hacer esto. Si desea una copia que sea una fusión, use copiar (o deepcopy, dependiendo de lo que desee) y luego actualizar. Las dos líneas de código son mucho más legibles-más pitónicas-que la creación de una sola línea con .elemento() + .elemento(). Lo explícito es mejor que lo implícito.

Además, cuando se usa .items () (pre Python 3.0), está creando una nueva lista que contiene los elementos de la dict. Si sus diccionarios son grandes, entonces eso es bastante sobrecarga (dos listas grandes que se desecharán tan pronto como se cree el diccionario fusionado). update () puede funcionar de manera más eficiente, porque puede correr a través del segundo dict elemento por elemento.

En términos de tiempo :

>>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.52571702003479
>>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.694622993469238
>>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
41.484580039978027

IMO la pequeña desaceleración entre los dos primeros vale la pena por la legibilidad. Además, los argumentos de palabras clave para la creación de diccionarios solo se agregaron en Python 2.3, mientras que copy () y update() funcionará en versiones anteriores.

 171
Author: Tony Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-05 23:56:02

En una respuesta de seguimiento, usted preguntó sobre el rendimiento relativo de estas dos alternativas:{[23]]}

z1 = dict(x.items() + y.items())
z2 = dict(x, **y)

En mi máquina, al menos (un x86_64 bastante ordinario que ejecuta Python 2.5.2), la alternativa z2 no solo es más corta y simple, sino también significativamente más rápida. Puedes verificar esto por ti mismo usando el módulo timeit que viene con Python.

Ejemplo 1: diccionarios idénticos que se asignan 20 enteros consecutivos a sí mismos:

% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())'
100000 loops, best of 3: 5.67 usec per loop
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)' 
100000 loops, best of 3: 1.53 usec per loop

z2 gana por un factor de 3.5 más o menos. Diferentes diccionarios parecen dar resultados muy diferentes, pero z2 siempre parece salir adelante. (Si obtiene resultados inconsistentes para la prueba same , intente pasar -r con un número mayor que el predeterminado 3.)

Ejemplo 2: diccionarios no superpuestos que asignan 252 cadenas cortas a enteros y viceversa:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())'
1000 loops, best of 3: 260 usec per loop
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)'               
10000 loops, best of 3: 26.9 usec per loop

z2 gana por aproximadamente un factor de 10. Eso es una gran victoria en mi libro!

Después de comparar esos dos, me pregunté si El bajo rendimiento de z1 podría atribuirse a la sobrecarga de la construcción de las dos listas de elementos, lo que a su vez me llevó a preguntarme si esta variación podría funcionar mejor:

from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))

Algunas pruebas rápidas, por ejemplo,

% python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))'
10000 loops, best of 3: 66 usec per loop

Me lleva a concluir que z3 es algo más rápido que z1, pero no tan rápido como z2. Definitivamente no vale la pena toda la mecanografía extra.

A esta discusión todavía le falta algo importante, que es una comparación de rendimiento de estas alternativas con la forma "obvia" de fusionar dos listas: usando el método update. Para tratar de mantener las cosas en pie de igualdad con las expresiones, ninguna de las cuales modifica x o y, voy a hacer una copia de x en lugar de modificarla en el lugar, de la siguiente manera:

z0 = dict(x)
z0.update(y)

Un resultado típico:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)'
10000 loops, best of 3: 26.9 usec per loop

En otras palabras, z0 y z2 parecen tener un rendimiento esencialmente idéntico. ¿Crees que esto podría ser una coincidencia? Yo no....

De hecho, yo iría tan lejos como para afirmar que es imposible para que el código Python puro haga algo mejor que esto. Y si puedes hacerlo significativamente mejor en un módulo de extensión C, imagino que la gente de Python podría estar interesada en incorporar tu código (o una variación en tu enfoque) en el núcleo de Python. Python usa dict en muchos lugares; optimizar sus operaciones es un gran problema.

También podrías escribir esto como

z0 = x.copy()
z0.update(y)

Como lo hace Tony, pero (no es sorprendente) la diferencia en notación resulta no tener ningún efecto medible sobre la actuación. Usa lo que más te parezca. Por supuesto, tiene toda la razón al señalar que la versión de dos declaraciones es mucho más fácil de entender.

 118
Author: zaphod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-10 02:32:55

Quería algo similar, pero con la capacidad de especificar cómo se fusionaron los valores en las claves duplicadas, así que hackeé esto (pero no lo probé en gran medida). Obviamente esto no es una sola expresión, pero es una sola llamada a la función.

def merge(d1, d2, merge_fn=lambda x,y:y):
    """
    Merges two dictionaries, non-destructively, combining 
    values on duplicate keys as defined by the optional merge
    function.  The default behavior replaces the values in d1
    with corresponding values in d2.  (There is no other generally
    applicable merge strategy, but often you'll have homogeneous 
    types in your dicts, so specifying a merge technique can be 
    valuable.)

    Examples:

    >>> d1
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1)
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1, lambda x,y: x+y)
    {'a': 2, 'c': 6, 'b': 4}

    """
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge_fn(result[k], v)
        else:
            result[k] = v
    return result
 86
Author: rcreswick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-13 19:56:21

En Python 3, puede usar colecciones.Mapa de cadena que agrupa varios dicts u otras asignaciones para crear una única vista actualizable:

>>> from collections import ChainMap
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = ChainMap({}, y, x)
>>> for k, v in z.items():
        print(k, '-->', v)

a --> 1
b --> 10
c --> 11
 77
Author: Raymond Hettinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-27 08:12:41

Actualización recursiva / profunda de un dict

def deepupdate(original, update):
    """
    Recursively update a dict.
    Subdict's won't be overwritten but also updated.
    """
    for key, value in original.iteritems(): 
        if key not in update:
            update[key] = value
        elif isinstance(value, dict):
            deepupdate(value, update[key]) 
    return update

Demostración:

pluto_original = {
    'name': 'Pluto',
    'details': {
        'tail': True,
        'color': 'orange'
    }
}

pluto_update = {
    'name': 'Pluutoo',
    'details': {
        'color': 'blue'
    }
}

print deepupdate(pluto_original, pluto_update)

Salidas:

{
    'name': 'Pluutoo',
    'details': {
        'color': 'blue',
        'tail': True
    }
}

Gracias rednaw por las ediciones.

 61
Author: Stan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-18 11:19:15

La mejor versión que podría pensar sin usar copy sería:

from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))

Es más rápido que dict(x.items() + y.items()) pero no tan rápido como n = copy(a); n.update(b), al menos en CPython. Esta versión también funciona en Python 3 si cambia iteritems() a items(), lo que se hace automáticamente con la herramienta 2to3.

Personalmente me gusta más esta versión porque describe bastante bien lo que quiero en una sola sintaxis funcional. El único problema menor es que no hace completamente obvio que los valores de y tengan prioridad sobre los valores de x, pero no creo que sea difícil de averiguar.

 54
Author: driax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-14 18:55:15

Python 3.5 (PEP 448) permite una opción de sintaxis más agradable:

x = {'a': 1, 'b': 1}
y = {'a': 2, 'c': 2}
final = {**x, **y} 
final
# {'a': 2, 'b': 1, 'c': 2}

O incluso

final = {'a': 1, 'b': 1, **x, **y}
 42
Author: Bilal Syed Hussain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 21:27:52
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

Para los elementos con claves en ambos diccionarios ('b'), puede controlar cuál termina en la salida poniendo esa última.

 40
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-02 07:49:27

Mientras que la pregunta ya ha sido contestada varias veces, esta solución simple al problema aún no se ha enumerado.

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)

Es tan rápido como z0 y el mal z2 mencionado anteriormente, pero fácil de entender y cambiar.

 35
Author: phobie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-14 16:12:33
def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

Entre tales respuestas sombrías y dudosas, este brillante ejemplo es la única y buena manera de fusionar los dictados en Python, respaldado por dictador for life Guido van Rossum mismo! Alguien más sugirió la mitad de esto, pero no lo puso en una función.

print dict_merge(
      {'color':'red', 'model':'Mini'},
      {'model':'Ferrari', 'owner':'Carl'})

Da:

{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
 33
Author: Sam Watkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-06 09:30:07

Si crees que los lambdas son malvados, entonces no leas más. Según lo solicitado, puede escribir la solución rápida y eficiente en memoria con una expresión:

x = {'a':1, 'b':2}
y = {'b':10, 'c':11}
z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y)
print z
{'a': 1, 'c': 11, 'b': 10}
print x
{'a': 1, 'b': 2}

Como se sugirió anteriormente, usar dos líneas o escribir una función es probablemente una mejor manera de hacerlo.

 25
Author: EMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 18:20:48

Ser python. Use una comprensión :

z={i:d[i] for d in [x,y] for i in d}

>>> print z
{'a': 1, 'c': 11, 'b': 10}
 20
Author: Robino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-29 10:45:25

En python3, el método items ya no devuelve una lista, sino una vista , que actúa como un conjunto. En este caso necesitarás tomar el conjunto union ya que concatenar con + no funcionará:

dict(x.items() | y.items())

Para el comportamiento similar a python3 en la versión 2.7, el método viewitems debería funcionar en lugar de items:

dict(x.viewitems() | y.viewitems())

Prefiero esta notación de todos modos, ya que parece más natural pensar en ella como una operación de unión conjunto en lugar de concatenación (como el título Mostrar).

Editar:

Un par de puntos más para python 3. Primero, tenga en cuenta que el truco dict(x, **y) no funcionará en python 3 a menos que las claves en y sean cadenas.

Además, la respuesta del Chainmap de Raymond Hettinger es bastante elegante, ya que puede tomar un número arbitrario de dictados como argumentos, pero de los documentos parece que busca secuencialmente a través de una lista de todos los dictados para cada búsqueda:{[14]]}

Búsquedas buscar el subyacente asignaciones sucesivas hasta encontrar una clave.

Esto puede ralentizarte si tienes muchas búsquedas en tu aplicación:

In [1]: from collections import ChainMap
In [2]: from string import ascii_uppercase as up, ascii_lowercase as lo; x = dict(zip(lo, up)); y = dict(zip(up, lo))
In [3]: chainmap_dict = ChainMap(y, x)
In [4]: union_dict = dict(x.items() | y.items())
In [5]: timeit for k in union_dict: union_dict[k]
100000 loops, best of 3: 2.15 µs per loop
In [6]: timeit for k in chainmap_dict: chainmap_dict[k]
10000 loops, best of 3: 27.1 µs per loop

Así que alrededor de un orden de magnitud más lento para las búsquedas. Soy un fan de Chainmap, pero parece menos práctico donde puede haber muchas búsquedas.

 19
Author: beardc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:53

Abuso que conduce a una solución de una sola expresión para La respuesta de Matthew :

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (lambda f=x.copy(): (f.update(y), f)[1])()
>>> z
{'a': 1, 'c': 11, 'b': 10}

Dijiste que querías una expresión, así que abusé de lambda para enlazar un nombre, y tuplas para anular el límite de una expresión de lambda. Siéntete libre de encogerte.

También podrías hacer esto, por supuesto, si no te importa copiarlo:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
 14
Author: Claudiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:53

Solución simple usando itertools que preserva el orden (los últimos dictados tienen prioridad)

import itertools as it
merge = lambda *args: dict(it.chain.from_iterable(it.imap(dict.iteritems, args)))

Y su uso:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> merge(x, y)
{'a': 1, 'b': 10, 'c': 11}

>>> z = {'c': 3, 'd': 4}
>>> merge(x, y, z)
{'a': 1, 'b': 10, 'c': 3, 'd': 4}
 13
Author: reubano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-06 11:30:16

Dos diccionarios

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

n diccionarios

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))

sum tiene mal rendimiento. Véase https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python /

 11
Author: Mathieu Larose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-02 18:16:17

En python 3:

import collections
a = {1: 1, 2: 2}
b = {2: 3, 3: 4}
c = {3: 5}

r = dict(collections.ChainMap(a, b, c))
print(r)

Fuera:

{1: 1, 2: 2, 3: 4}

Docs: https://docs.python.org/3/library/collections.html#collections.ChainMap :

 11
Author: Skyduy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-24 07:24:50

Aunque las respuestas eran buenas para este diccionario superficial, ninguno de los métodos definidos aquí en realidad hacen una fusión profunda del diccionario.

Ejemplos siguen:

a = { 'one': { 'depth_2': True }, 'two': True }
b = { 'one': { 'extra': False } }
print dict(a.items() + b.items())

Uno esperaría un resultado de algo como esto:

{ 'one': { 'extra': False', 'depth_2': True }, 'two': True }

En cambio, obtenemos esto:

{'two': True, 'one': {'extra': False}}

La entrada 'one' debería haber tenido 'depth_2' y 'extra' como elementos dentro de su diccionario si realmente era una fusión.

Usando cadena también, no funciona:

from itertools import chain
print dict(chain(a.iteritems(), b.iteritems()))

Resultados en:

{'two': True, 'one': {'extra': False}}

La fusión profunda que rcwesick dio también crea el mismo resultado.

Sí, funcionará para fusionar los diccionarios de muestra, pero ninguno de ellos es un mecanismo genérico para fusionar. Actualizaré esto más tarde una vez que escriba un método que haga una verdadera fusión.

 9
Author: Thanh Lim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-03 23:36:50

Para Python 2:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()+y.items())
print(z)

Para Python 3:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()|y.items())
print(z)

Da salida: {'a': 1, 'c': 11, 'b': 10}

 8
Author: Kalpesh Dusane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-01 06:29:01

A partir de ideas aquí y en otros lugares he comprendido una función:

def merge(*dicts, **kv): 
      return { k:v for d in list(dicts) + [kv] for k,v in d.items() }

Uso (probado en python 3):

assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\
    {1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'})

assert (merge(foo='bar')=={'foo': 'bar'})

assert (merge({1:11},{1:99},foo='bar',baz='quux')==\
    {1: 99, 'foo': 'bar', 'baz':'quux'})

assert (merge({1:11},{1:99})=={1: 99})

Podrías usar una lambda en su lugar.

 7
Author: Bijou Trouvaille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-19 05:49:19
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x, z = dict(x), x.update(y) or x
>>> x
{'a': 1, 'b': 2}
>>> y
{'c': 11, 'b': 10}
>>> z
{'a': 1, 'c': 11, 'b': 10}
 5
Author: John La Rooy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-13 10:01:31

El problema que tengo con las soluciones listadas hasta la fecha es que, en el diccionario fusionado, el valor para la clave "b" es 10 pero, a mi manera de pensar, debería ser 12. En ese sentido, presento lo siguiente:

import timeit

n=100000
su = """
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
"""

def timeMerge(f,su,niter):
    print "{:4f} sec for: {:30s}".format(timeit.Timer(f,setup=su).timeit(n),f)

timeMerge("dict(x, **y)",su,n)
timeMerge("x.update(y)",su,n)
timeMerge("dict(x.items() + y.items())",su,n)
timeMerge("for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] ",su,n)

#confirm for loop adds b entries together
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]
print "confirm b elements are added:",x

Resultados:

0.049465 sec for: dict(x, **y)
0.033729 sec for: x.update(y)                   
0.150380 sec for: dict(x.items() + y.items())   
0.083120 sec for: for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]

confirm b elements are added: {'a': 1, 'c': 11, 'b': 12}
 5
Author: upandacross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-03 18:11:54

Esto se puede hacer con una sola comprensión dict:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> { key: y[key] if key in y else x[key]
      for key in set(x) + set(y)
    }

En mi opinión, la mejor respuesta para la parte de 'expresión única' ya que no se necesitan funciones adicionales, y es corta.

 5
Author: RemcoGerlich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-17 14:47:23
from collections import Counter
dict1 = {'a':1, 'b': 2}
dict2 = {'b':10, 'c': 11}
result = dict(Counter(dict1) + Counter(dict2))

Esto debería resolver su problema.

 5
Author: reetesh11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-30 13:04:00

(Solo para Python2.7*; hay soluciones más simples para Python3*.)

Si no eres reacio a importar un módulo de biblioteca estándar, puedes hacer

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

(El bit or a en el lambda es necesario porque dict.update siempre devuelve None en caso de éxito.)

 5
Author: kjo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-28 13:13:27

En Python 3.5 puedes usar unpack ** para crear un nuevo diccionario. Este método no ha sido mostrado en respuestas anteriores. Además, es mejor usar {} en lugar de dict(). Porque {} es un literal de python y dict() implica una llamada a una función.

dict1 = {'a':1}
dict2 = {'b':2}
new_dict = {**dict1, **dict2}
>>>new_dict
{'a':1, 'a':2}
 5
Author: levi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-28 00:33:55