2012-02-14 113 views
5

我不知道該怎麼稱呼我在找什麼;所以如果我沒有在其他地方找到這個問題,我很抱歉。簡而言之,我正在編寫將直接與Linux內核接口的Python代碼。它容易得到所需的值從包含頭文件,並將它們在我的源寫: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 

它易於構建結構時發送到內核中使用這些值。但是,它們幾乎沒有幫助解決內核響應中的值。

如果我把值放在字典中,我將不得不掃描字典中的所有值,以查找內核中每個結構中每個項的鍵我推測。必須有一個更簡單,更有效的方法。

你會怎麼做? (隨意標題改成了問題,如果它的方式關閉)

+1

製作2個字母,一個映射到每個方向,也許?如果你的映射不可能改變,這將是有效的。 – 2012-02-14 19:34:43

+0

我想你要求的是在這裏回答http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python。如果你只是想pythonic,而不是快速:filter(lambda k:a [k] == 3,a)給你IFA_LABEL – 2012-02-14 19:35:52

+1

@JoelCornett:請發表你的答案作爲答案,以便它可以正確投票。 – 2012-02-14 20:00:06

回答

9

如果你想使用兩個類型的字典,你可以試試這個創建倒字典:

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

當這些值不唯一時,這會導致巨大的問題。但是,從這個問題來看,這些值似乎是獨一無二的。因此,這是字典構造函數的優雅使用。比'dict'((a [k],k)'a')中的k更清潔一些。 – 2012-02-14 21:04:52

1

我最終什麼事做的是離開恆值在模塊中並創建一個字典。該模塊是ip_addr.py(這些值來自linux/if_addr.h),因此在構建發送到內核的結構時,我可以使用if_addr.IFA_LABEL並解決與if_addr.values[2]的響應。我希望這是最直接的,所以當我不得不在此再看看一年+它很容易理解:對

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

您的解決方案留下了很多的工作要做重複創建文件的人。這是錯誤的來源(你實際上必須寫下每個名字三次)。如果你有一個需要不時更新的文件(比如,當新的內核版本出來時),你註定會遲早包含一個錯誤。實際上,這只是一個很長的說法,你的解決方案違反了DRY

我會改變您的解決方案是這樣的:

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

這是values字典自動生成。根據該文件中的其他內容,您可能需要(或必須)更改if語句中的條件。可能類似於以下內容。該版本將不需要在if語句中列出前綴,但如果文件中包含其他內容,則會失敗。

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

你當然可以在那裏做些更復雜的事情,例如,檢查意外重複的值。