2010-12-14 23 views
0

我有一個名爲nesteddict類從collections.defaultdict衍生持有一組嵌套的字典:如何將派生的遞歸數據類型轉換爲基礎數據類型?

import collections 

class nesteddict(collections.defaultdict): 
    """Nested dictionary structure. 

    Based on Stack Overflow question 635483 
    """ 
    def __init__(self): 
     collections.defaultdict.__init__(self, nesteddict) 
     self.locked = False 

我想能夠執行一個操作,即轉換所有nesteddict對象來python-實例本地字典對象。要做到這一點

一種方法是有一個方法:

def todict(self): 
    for (key,val) in self.iteritems(): 
     if isinstance(val,nesteddict): 
      val.todict() 
      self[key] = dict(val) 
    self = dict(self) 

這是成功地用字典類型更換所有的內部映射對象,但在方法的最後一條語句顯然是行不通的。

下面是一個例子:

In [93]: a = pyutils.nesteddict() 

In [94]: a[1][1] = 'a' 

In [95]: a[1][2] = 'b' 

In [96]: a[2][1] = 'c' 

In [97]: a[2][2] = 'd' 

In [98]: print a 
defaultdict(<class 'pyutils.nesteddict'>, {1: defaultdict(<class 'pyutils.nesteddict'>, {1: 'a', 2: 'b'}), 2: defaultdict(<class 'pyutils.nesteddict'>, {1: 'c', 2: 'd'})}) 

In [99]: a.todict() 

In [100]: print a 
defaultdict(<class 'pyutils.nesteddict'>, {1: {1: 'a', 2: 'b'}, 2: {1: 'c', 2: 'd'}}) 

有沒有辦法在Python做到這一點?有一種將其對象轉換爲另一種類型的方法?如果不是,這是一個很好的選擇。請注意,實際中的數據類型可能很大,因此最好不要僅複製並返回它。

謝謝!
Uri

+3

「我會就像能夠執行操作的一個實例一樣,將所有嵌套對象轉換爲Python本地字典對象。 「爲什麼?它已經是一個'dict'對象。你不需要轉換任何東西。它是'defaultdict'的一個子類,這意味着它**是** dict'。 – 2010-12-14 18:53:37

+0

加載數據後,我想「鎖定」它。實現這一點的一種方法是使default_factory方法成爲引發KeyError的函數,這看起來工作正常。但是,我在使用cPickle序列化這個類時遇到了麻煩。轉換爲純字典將允許輕鬆序列化(包括使用json),並將以類似的方式有效地鎖定字典。 – 2010-12-16 20:03:44

+0

@ S.Lott pickle是想要轉換爲純字典的常見原因:否則,要取消它,你需要帶上專用字典的定義,例如。 'infinite_defaultdict = lambda:defaultdict(infinite_defaultdict)'。 – 2013-09-06 13:24:13

回答

5

做它作爲一個免費的功能,而你在它,考慮更多的功能式的方法:

def undefaulted(x): 
    return dict(
    (k, undefaulted(v)) 
    for (k, v) in x.iteritems() 
) if isinstance(x, nesteddict) else x 

a = undefaulted(a) 
+0

這很好。謝謝! – 2010-12-16 20:04:59

+0

對於未來的訪問者:使用詞典理解的另一個答案確實比使用'dict()'要好。除了@傑米的說法,它也更快*和*更習慣。 – 2015-01-29 13:08:32

1

dict(a)會給你一個來自defaultdict派生的任何對象的默認字典。也就是說,假設你不需要重寫所需的特殊方法。

+0

是的,但它不會遞歸地嵌入到字典中。它只會將頂級nesteddict對象轉換爲字典。 – 2010-12-16 20:04:23

+0

呀..完全忘了請求的遞歸部分。我的錯。 – dietbuddha 2010-12-16 20:19:14

0

我在你的代碼注意到的第一件事,就是你正在修改(或試圖)self變量。該變量只是指向您班級的當前實例。如果您重新分配它,則只需將它指向另一個值,但self指向的先前值保持不變。這就是Python的工作原理。

所以,你應只是返回轉換的結果在你的方法......是這樣的:

def anothertodict(self): 
    stuff = dict(self) 
    for (key,val) in stuff.iteritems(): 
     if isinstance(val,nesteddict): 
      stuff[key] = val.anothertodict() 
    return stuff 

這樣一來,如果你做一個:print a.anothertodict(),你會得到你期待着得到。

PS:爲什麼你需要從defaultdict轉換爲字典?

3

我剛剛使用嵌套的defaultdicts面臨這個問題。我的解決辦法:

def dictify(d): 
    return {k:dictify(v) for k,v in d.items()} if \ 
     isinstance(d,nesteddict) else d 

這是更好地使用{}而不是字典(),因爲調用 構造字典()的限制的關鍵字參數 數量255參見:What is a maximum number of arguments in a Python function?