2010-10-20 22 views
5

我對Python比較陌生,想知道我是否在重新發明輪子或以非pythonic方式做事 - 讀錯了。基於字典的switch-like語句與動作

我正在重寫最初寫在Lua中的一些解析器。有一個函數接受來自導入表及其值的字段名稱,對值進行一些操作並將其存儲在目標字典中的適當鍵名下。

在原始代碼中,它是通過具有匿名函數的長開關式語句作爲動作解決的。 Python代碼如下所示:

class TransformTable: 
    target_dict = {} 
    ... 
    def mapfield(self, fieldname, value): 
     try: 
      { 
       'productid': self.fn_prodid, 
       'name': self.fn_name, 
       'description': self.fn_desc, 
       ... 
      }[fieldname](value) 
     except KeyError: 
      sys.stderr.write('Unknown key !\n') 

    def fn_name(val): 
     validity_check(val) 
     target_dict['Product'] = val.strip().capitalize() 
    ... 

每一個「現場處理」功能做不同的動作,並存儲在不同的密鑰在target_dict,當然。 由於Python不支持帶語句的匿名函數(或者我錯過了某些東西?),函數必須單獨編寫,代碼不易讀且不必要的複雜。

任何提示如何以更優雅和更pythonic的方式做這樣的任務表示讚賞。

THX

大衛

+0

你可能還想花一些努力避免在發佈之前通過搜索類似的問題來重新發現問題。 – martineau 2010-10-21 08:15:16

回答

0

我前段時間在我的answer中應用了類似於@Matti Virkkunen'a的方法,解決了標題爲「switch case in python doesn't work; need another pattern」的問題。它還演示了處理未知領域的相對簡單和優雅的方式。在你的例子中音譯爲:

class TransformTable: 
    target_dict = {} 

    def productid(self, value): 
     ... 
    def name(self, value): 
     validity_check(value) 
     self.target_dict['Product'] = value.strip().capitalize() 
    def description(self, value): 
     ... 

    def _default(self, value): 
     sys.stderr.write('Unknown key!\n') 

    def __call__(self, fieldname, value): 
     getattr(self, fieldname, self._default)(value) 

transformtable = TransformTable() # create callable instance 

transformtable(fieldname, value) # use it 
+1

這是一個更清潔的解決方案。謝謝。如果字段名稱(從導入表中提取)將包含unicode字符(帶有變音符號),這將如何工作,即。用非ASCII名稱定義函數? – 2010-10-21 12:45:44

+0

要使用顯示的機制,需要從正在切換到有效標識符名稱的某種映射。上面它假設它是1:1。處理這個問題的另一種更通用的方法是創建一個單獨的字典或查找表,它將每個有效輸入(此處爲「fieldname」)映射到唯一的方法名稱 - 可以簡單地爲'method1','method2'等。在整數值上,你​​有類似'case_'+ str(number)'。映射不需要是1:1,因爲例如幾個輸入都可以用相同的方法處理。您可以隨心所欲地自定義它。 – martineau 2010-10-21 16:00:58

+0

Thx澄清。所以我的原始解決方案與1:1的字典在try部分的映射接近此。 – 2010-10-21 16:33:57

1

如果通過任何可能的手段,您可以根據場上的名字命名的成員函數,只是做這樣的事情:

getattr(self, "fn_" + fieldname)(value) 

編輯:您可以使用hasattr來檢查函數是否存在,而不是期待KeyError。或期望一個AttributeError。無論如何,您應該只在try..except內部存取訪問權限,並在外部調用它,否則在某個字段方法中導致的KeyError可能會被誤解。

+0

功能名稱泛化的好主意。 – 2010-10-20 22:54:45

+0

功能名稱泛化的好主意。是否還有一種更一般的詞典 - >字典映射(鍵值轉換的關鍵)? – 2010-10-20 23:03:44

+0

我認爲這是在類上下文中切換字符串的標準方式。我懶得找到鏈接,但我知道Guido已經將其稱爲非常優雅的解決方案。他是荷蘭人,所以對他來說,一條正確的道路是顯而易見的。 – aaronasterling 2010-10-21 06:39:39