2016-11-21 34 views
0

我正在開發一個python實用程序。其中一部分是生成文件索引
python可以在不知道深度的情況下動態訪問多維字典嗎?
也就是說,如果我有示例數據:
example = {'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}}
有沒有一種方法,我可以訪問與類似 example["main","2","1"]並返回2-1什麼元素? 我知道我可以寫我自己的潛水算法,但是我的經驗表明你不能寫入價值。
使用[「key」,「key2」]訪問Python Dictionarys

+0

你說的「不能再寫入值」是什麼意思? –

+0

你總是可以做'example ['main'] ['2'] ['1']'。當然,你必須知道你的鍵('main','2'和'1') – lucasnadalutti

+0

爲什麼你比'example [「需要'example [」main「,」2「,」1「]'''主 「] [」 2 「] [」 1" ]'? – thorhunter

回答

0

如果您確實需要這樣做,您需要推出自己的字典類。幸運的是,您可以繼承__getitem__以外的所有內容,從dict繼承。

class MyDict(dict): 
    def __getitem__(self, keys): 
     if isinstance(keys, str): 
      # this special-case saves you if you try to do normal indexing 
      # on a string. 
      return super().__getitem__(keys) 
     cur = self 
     for key in keys: 
      cur = cur.get(key, {}) 
      # the default option here returns an empty dict instead 
      # of raising a KeyError. That might not be what you want 
     return cur 

注意,這將刪除你的元組核心能力,所以像{("some", "tuple", "values"): "any value"}鍵/瓦爾斯將無法訪問,除非特別編碼。這可能看起來像...

... 
     for i, key in enumerate(keys): 
      if keys[i:] in cur: 
       return cur[keys[i:]] 
      cur = cur.get(key, {}) 

然後,您可以將您的映射投射到這個新的字典並以這種方式進行搜索。

example = {'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}} 
result = MyDict2(example)['2', '2', '1'] 

您何況有本以及設定值,在這種情況下也繼承__setitem__

class MyDict(dict): 
    def __getitem__(self, keys): 
     # as above 
    def __setitem__(self, keys, value): 
     if isinstance(keys, str): 
      super().__setitem__(keys, value) 
     cur = self 
     for key in keys[:-1]: 
      cur = cur.setdefault(key, {}) 
     cur[keys[-1]] = value 
+1

他提到賦值給那些嵌套的字典值,所以你可能想添加'__setitem __()'以及 – Aaron

+0

@Aaron嗯它不工作,刪除'直到我得到它的測試和可運行 - 但好點! –

+0

不應該'super().__ setitem __(keys,value)'是'return super()。__setitem __(鍵,值)'沒有返回,它會創建一個奇怪的條目負載。 –

0

可以使這樣的功能:

def get_item(d, keys): 
    current = d 
    for k in keys: 
     current = current[k] # You can add some error handling here 
    return current 

使用示例:https://repl.it/E49o/1

如果你要修改的最後索引處的值,你可以做這樣的事情。

def set_item(d, keys, new_value): 
    current = d 
    for k in keys[:-1]: # All the keys except the last one 
     current = current[k] 
    current[keys[-1]] = new_value 
+0

我創建了類似的東西,問題是沒有辦法(我可以看到)使用一個類似的函數來設置值。 –

+0

我用setter修改了我的答案。 – Arya

0

您也可以包裝在派生類字典由@Arya提出的想法,例如:

class ListAccess(dict): 
    def __getitem__(self, item): 
     if type(item) in [tuple,list]: 
      item = list(item) 
      ret = self 
      while True: 
       try: 
        ret = ret[item.pop(0)] 
       except IndexError: 
        break 
      return ret 
     else: 
      return super(ListAccess, self).__getitem__(item) 

store = ListAccess({'main': {'2': {'2': '2-2', '1': '2-1'}, '1': {'2': '1-2', '1': '1-1'}}}) 
print store['main','2','1']