2012-02-14 10 views
5

Non sono sicuro di cosa chiamare ciò che sto cercando; quindi se non riesco a trovare questa domanda altrove, mi scuso. In breve, sto scrivendo il codice Python che si interfaccia direttamente con il kernel di Linux. La sua facile per ottenere i valori richiesti da includere file di intestazione e scriverli a mia fonte:Mappatura bidirezionale 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 

sua facile da usare questi valori quando si costruiscono le strutture di inviare al kernel. Tuttavia, non sono quasi di nessun aiuto per risolvere i valori nelle risposte dal kernel.

Se metto i valori in DAT, dovrei scansionare tutti i valori nel dict per cercare le chiavi per ogni elemento in ogni struct dal kernel che presumo. Ci deve essere un modo più semplice ed efficiente.

Come lo faresti? (Sentitevi liberi di reintitolatelo alla domanda se il suo modo fuori)

+1

Crea 2 dts, uno mappato in ciascuna direzione, forse? Ciò sarebbe efficace se le tue mappature non dovessero cambiare. –

+0

Penso che quello che chiedi sia risposto qui http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python. Se vuoi solo pythonic, non veloce: filter (lambda k: a [k] == 3, a) ti dà IFA_LABEL –

+1

@JoelCornett: Si prega di postare la risposta come risposta in modo che possa essere votato correttamente. –

risposta

9

Se si desidera utilizzare due dicts, si può provare questo per creare il dict invertita:

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

Ciò causa enormi problemi quando i valori non sono univoci. Tuttavia, dalla domanda, sembra che i valori siano probabilmente unici. Pertanto, questo è un uso elegante di un costruttore di dizionari. Un po 'più pulito di 'dict ((a [k], k) per k in a)'. –

1

Quello che ho finito per fare è lasciare la costante valori nel modulo e creazione di un dett. Il modulo è ip_addr.py (i valori sono da linux/if_addr.h), quindi quando si costruiscono le strutture da inviare al kernel posso usare if_addr.IFA_LABEL e risolvere le risposte con if_addr.values[2]. Spero che questo sia il più semplice in modo che quando devo guardare a questo nuovo in un anno + è facile da capire: 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

La soluzione lascia un sacco di lavoro fare la persona ripete la creazione del file. Questa è una fonte di errore (in realtà devi scrivere ogni nome tre volte). Se si dispone di un file in cui è necessario aggiornarli di tanto in tanto (ad esempio, quando vengono rilasciate nuove versioni del kernel), si è destinati a includere un errore prima o poi. In realtà, questo era solo un modo lungo di dire, la tua soluzione viola DRY.

vorrei cambiare la vostra soluzione a qualcosa di simile:

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_')} 

Questo è stato il values dict viene generato automaticamente. Potresti volere (o dover) modificare la condizione nell'istruzione if, in base a qualsiasi altra cosa in quel file. Forse qualcosa come il seguente. Quella versione toglierebbe la necessità di elencare i prefissi nell'istruzione if, ma fallirebbe se tu avessi altre cose nel file.

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

Si potrebbe ovviamente fare qualcosa di più sofisticato lì, ad es. verificare i valori ripetuti accidentalmente.