já foi respondido, mas como várias pessoas mencionaram a reversão do dicionário, veja como você faz isso em uma linha (assumindo o mapeamento 1: 1) e alguns dados de perf:
python 2.6:
reversedict = dict([(value, key) for key, value in mydict.iteritems()])
2.7+:
reversedict = {value:key for key, value in mydict.iteritems()}
se você acha que não é 1: 1, ainda pode criar um mapeamento reverso razoável com algumas linhas:
reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]
quão lenta é essa: mais lenta que uma pesquisa simples, mas não tão lenta quanto você imagina - em um dicionário de entradas 100000 'direto', uma pesquisa 'rápida' (ou seja, procurando um valor que deve estar no início das teclas) foi cerca de 10x mais rápido do que reverter o dicionário inteiro e uma pesquisa "lenta" (no final) cerca de 4-5x mais rápido. Então, depois de no máximo 10 pesquisas, é pago por si próprio.
a segunda versão (com listas por item) leva cerca de 2,5x enquanto a versão simples.
largedict = dict((x,x) for x in range(100000))
# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop
# Should be fast, has to only search 9 entries to find it.
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop
# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.
In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop
In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop
In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop
In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop
Também teve alguns resultados interessantes com o ifilter. Teoricamente, se o filtro deve ser mais rápido, podemos usar itervalues () e possivelmente não precisamos criar / passar por toda a lista de valores. Na prática, os resultados foram ... estranhos ...
In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop
In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop
Portanto, para pequenas compensações, foi dramaticamente mais rápido que qualquer versão anterior (2,36 * u * S vs. um mínimo de 1,48 * m * S para casos anteriores). No entanto, para grandes compensações perto do final da lista, foi drasticamente mais lenta (15,1ms vs. o mesmo 1,48mS). As pequenas economias na parte baixa não valem o custo na parte alta, imho.