Há outras maneiras de fazer isso além do dict.update com dict.pop...Mas a parte que me parece mais relevante é evitar a alteração dos dicionários originais, para caso estes sejam utilizados em outros contextos. Usando:
d1 = {'Ex1': 'Teste', 'Ex2': 10}
d2 = {'Ex3': 'Teste2', 'Ex4': 'Teste3'}
Algumas maneiras de obter um "d3" que é a união dos dicionários sem o mapeamento da chave "Ex3", sem alterar os dicionários originais:
# Ainda com o update, Python 2 e 3
d3 = d1.copy()
d3.update(d2)
del d3["Ex3"] # A diferença é que dict.pop("Ex3") retorna/devolve o valor removido
# Python 2
d3 = dict(d1.items() + d2.items()) # Concatenação de listas
del d3["Ex3"]
# Python 3 (embora também funcione no Python 2)
from itertools import chain
d3 = dict(chain(d1.items(), d2.items())) # Concatenação de iteráveis quaisquer (deferred/lazy)
del d3["Ex3"]
# Python 2 com o método iteritems()
from itertools import chain
d3 = dict(chain(d1.iteritems(), d2.iteritems()))
# Sem querer usar um statement como o "del", deixando isso tudo como uma única expressão:
from itertools import chain
d3 = {k: v for k, v in chain(d1.items(), d2.items()) if k != "Ex3"}
# Até o import poderia ser uma expressão...
d3 = {k: v for k, v in __import__("itertools").chain(d1.items(), d2.items()) if k != "Ex3"}
# Com a função "iteritems" do six para compatibilidade entre Python 2 e 3.
from itertools import chain
from six import iteritems
d3 = {k: v for k, v in chain(iteritems(d1), iteritems(d2)) if k != "Ex3"}
# Com map, o chain.from_iterable só avalia iteritems(d2) depois de percorrer d1
from itertools import chain
from six import iteritems
from six.moves import map # itertools.imap no Python 2; built-in map no Python 3
d3 = {k: v for k, v in chain.from_iterable(map(iteritems, [d1, d2])) if k != "Ex3"}
# Se quiser avaliar todos os iteritems antes, não precisa se preocupar com a diferença dos "maps"
from itertools import chain
from six import iteritems
d3 = {k: v for k, v in chain(*map(iteritems, [d1, d2])) if k != "Ex3"}
# Generator expression ao invés do map
from itertools import chain
from six import iteritems
d3 = {k: v for k, v in chain.from_iterable(iteritems(d) for d in [d1, d2]) if k != "Ex3"}
# Caso "Ex3" não seja a única chave a ser deixada de lado, o "not in" pode ajudar:
from itertools import chain
from six import iteritems
d3 = {k: v for k, v in chain(*map(iteritems, [d1, d2])) if k not in ["Ex3"]}
# AudioLazy =D (poderia ser o xmap no lugar do imap)
from audiolazy import imap, iteritems, chain
d3 = {k: v for k, v in chain.from_iterable(imap(iteritems, [d1, d2])) if k not in ["Ex3"]}
# Lambda (o chain poderia ser o do itertools e o iteritems do six)
from audiolazy import chain, iteritems
mix_dict = lambda dicts, inv_keys=[]: {k: v for k, v in chain.from_iterable(iteritems(d) for d in dicts) if k not in inv_keys}
d3 = mix_dict([d1, d2], ["Ex3"])
# A mesma função sem a sintaxe como expressão (def ao invés de lambda)
from audiolazy import chain, iteritems
def mix_dict(dicts, inv_keys=[]):
return {k: v for k, v in chain.from_iterable(iteritems(d) for d in dicts) if k not in inv_keys}
d3 = mix_dict([d1, d2], ["Ex3"])