2012-02-14 22 views
5

No estoy seguro de a qué llamar lo que estoy buscando; entonces si no puedo encontrar esta pregunta en otra parte, me disculpo. En resumen, estoy escribiendo código python que se conectará directamente con el kernel de Linux. Es fácil de obtener los valores requeridos de incluir archivos de cabecera y escribirlos en mi fuente:mapeo bidireccional de Python

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 

su fácil de usar estos valores en la construcción de estructuras para enviar al núcleo. Sin embargo, casi no ayudan a resolver los valores en las respuestas del kernel.

Si pongo los valores en dict, tendré que escanear todos los valores en el dicto para buscar claves para cada elemento en cada estructura del kernel, supongo. Debe haber una manera más simple y más eficiente.

¿Cómo lo harías? (No dude en cambiar el título de la pregunta de si su camino fuera)

+1

Haga 2 dictados, uno asignado en cada dirección, tal vez? Esto sería eficiente si no es probable que sus asignaciones cambien. –

+0

Creo que lo que pide se responde aquí http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python. Si solo desea python, no rápido: filter (lambda k: a [k] == 3, a) le da IFA_LABEL –

+1

@JoelCornett: publique su respuesta como respuesta para que pueda votar correctamente. –

Respuesta

9

Si desea utilizar dos dicts, puede intentar esto para crear el dict invertida:

b = {v: k for k, v in a.iteritems()} 
+0

Esto causa enormes problemas cuando los valores no son únicos. Sin embargo, de la pregunta, parece que los valores son probablemente únicos. Por lo tanto, este es un uso elegante de un constructor de diccionario. Algo más limpio que 'dict ((a [k], k) para k en a)'. –

1

Lo que terminé haciendo es dejando la constante valores en el módulo y la creación de un dict. El módulo es ip_addr.py (los valores son de linux/if_addr.h) entonces al construir estructuras para enviar al kernel puedo usar if_addr.IFA_LABEL y resuelvo las respuestas con if_addr.values[2]. Estoy esperando que esto es lo más sencillo así que cuando tengo que mirar esto otra vez en un año + es fácil de entender: p

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 
__IFA_MAX  = 8 

values = { 
      IFA_UNSPEC : 'IFA_UNSPEC', 
      IFA_ADDRESS : 'IFA_ADDRESS', 
      IFA_LOCAL  : 'IFA_LOCAL', 
      IFA_LABEL  : 'IFA_LABEL', 
      IFA_BROADCAST : 'IFA_BROADCAST', 
      IFA_ANYCAST : 'IFA_ANYCAST', 
      IFA_CACHEINFO : 'IFA_CACHEINFO', 
      IFA_MULTICAST : 'IFA_MULTICAST', 
      __IFA_MAX  : '__IFA_MAX' 
     } 
2

Su solución deja mucho trabajo hacer que la persona se repite la creación del archivo. Esa es una fuente de error (en realidad tiene que escribir cada nombre tres veces). Si tiene un archivo en el que necesita actualizarlos periódicamente (como, por ejemplo, cuando salen nuevas versiones del kernel), está destinado a incluir un error tarde o temprano. En realidad, eso fue solo una manera larga de decir que su solución infringe DRY.

que cambiaría su solución a algo como esto:

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 
__IFA_MAX  = 8 

values = {globals()[x]:x for x in dir() if x.startswith('IFA_') or x.startswith('__IFA_')} 

Este fue el dict values se genera de forma automática. Es posible que desee (o tenga que) cambiar la condición en la instrucción if allí, de acuerdo con cualquier otra cosa que esté en ese archivo. Tal vez algo como lo siguiente. Esa versión eliminaría la necesidad de listar prefijos en la sentencia if, pero fallaría si tuviera otras cosas en el archivo.

values = {globals()[x]:x for x in dir() if not x.endswith('__')} 

Por supuesto, podría hacer algo más sofisticado allí, por ejemplo. verificar valores repetidos accidentalmente

Cuestiones relacionadas