2013-05-13 21 views
1

我發現自己做這樣的事情不少:Python的設計模式進行數據轉換

if 'id' in kwargs: 
    query['_id'] = ObjectID(kwargs.pop('id')) 
if 'name' in kwargs: 
    query['event'] = kwargs.pop('name') 
if 'keywords' in kwargs: 
    keywords = kwargs.pop('keywords') 
    query['keywords'] = { 
     '$in': keywords 
    } 

忽略的實現細節。這裏的重點是我正在處理兩個共享類似數據並執行簡單,重複和更復雜轉換的數據結構。

是否有任何設計模式或其他開發人員友好的方式使這些類型的轉換更容易編碼?

我想過創建一個表格和相關的函數來轉換簡單的屬性名稱,但我有一種感覺,在處理更復雜的數據轉換時不會奏效。而且,從長遠來看,這種方法可能無法爲我節省大量的工作。

有什麼建議嗎?

+0

你跟MongoDB的工作疑問? – 2013-05-13 19:50:58

+0

是的。如果有一種方法可以讓Mongo變得更容易,我有興趣聽到它。然而,我真的在尋找一個'通用'的答案,因爲我在與MongoDB(或任何數據庫)完全無關之前遇到過這類問題。 – Kurtis 2013-05-13 19:52:46

+2

也許這是我自己的挑剔,但我不喜歡檢查密鑰是否存在在訪問它之前。我只需使用'try:...除了KeyError:pass'。如果你經常使用它,你可以創建一個上下文管理器,並使用'with SuppressKeyError():...'。 – Bakuriu 2013-05-13 21:26:45

回答

0

我現在要推薦的唯一事情就是至少只在一個地方進行這種轉換。因此,也許可以定義一個「kwargs to query」函數(最終也是相反的?),其中包含所有這些轉換。然後在需要進行此類轉換的地方使用該功能。

您可能可以創建一些更通用的方法來轉換單個值,但您也需要多次調用它。更不用說,你將不得不在通用轉換方法中添加許多特殊情況。相反,只需保留完整結構的轉換即可。

1

您至少可以用地圖清除if。當我有一大批轉換時,我喜歡這樣做。

transforms = {'id' : ('_id', lambda val: ObjectID(val)), 
       'name' : ('event', lambda val: val), 
       'keywords' : ('keywords', lambda val: val)} 
for kwargs_key in kwargs.keys(): 
    try: 
     query_key, transform = transforms[kwargs_key] 
    except KeyError: 
     # Default or error handling 
    else: 
     query[query_key] = transform(kwargs.pop(kwargs_key)) 

如果這個包裹在一個類,使transforms類或實例屬性,你甚至可以輕鬆地添加或者如果你想在運行時覆蓋變換。

1

你可能會考慮在一個類封裝轉換:

class QueryAdapter(object): 
    def __init__(self, **kwargs): 
     self.kwargs = kwargs 
    def __getitem__(self, item): 
     try: 
      method = getattr(self, item) 
     except AttributeError: 
      raise IndexError(item) 
     else: 
      return method() 
    def _id(self): 
     return 'ObjectID({})'.format(self.kwargs['id']) 
    def event(self): 
     return self.kwargs['name'] 
    def keywords(self): 
     return {'$in': self.kwargs['keywords']} 

一旦你定義了QueryAdapter,你的代碼的其餘部分就變得非常簡單:

kwargs = dict(id='abc', name='def') 
query = QueryAdapter(**kwargs) 

print(query['_id']) 
# ObjectID(abc) 
print(query['event']) 
# def 
print(query['keywords']) 
# {'$in': 'key'} 
+0

我真的很喜歡這個。它看起來是在多個地方使用此功能的好方法(Django Views,API Code和我的自定義Mongo模型)。我要試一試,看看它最終如何靈活和可重用。在我給每個人的建議一個鏡頭後,我一定會'接受'一個答案。謝謝! – Kurtis 2013-05-14 17:16:32