[英]How to convert defaultdict of defaultdicts [of defaultdicts] to dict of dicts [of dicts]?
使用這個答案 ,我創建了defaultdict
的defaultdict
。 現在,我想把那個深層嵌套的dict對象變回普通的python dict。
from collections import defaultdict
factory = lambda: defaultdict(factory)
defdict = factory()
defdict['one']['two']['three']['four'] = 5
# defaultdict(<function <lambda> at 0x10886f0c8>, {
# 'one': defaultdict(<function <lambda> at 0x10886f0c8>, {
# 'two': defaultdict(<function <lambda> at 0x10886f0c8>, {
# 'three': defaultdict(<function <lambda> at 0x10886f0c8>, {
# 'four': 5})})})})
我認為這不是正確的解決方案:
import json
regdict = json.loads(json.dumps(defdict))
# {u'one': {u'two': {u'three': {u'four': 5}}}}
此外, 這個答案是不充分的,因為它沒有遞歸嵌套的字典。
你可以在樹上遞歸,用dict理解產生的dict替換每個defaultdict
實例:
def default_to_regular(d):
if isinstance(d, defaultdict):
d = {k: default_to_regular(v) for k, v in d.items()}
return d
演示:
>>> from collections import defaultdict
>>> factory = lambda: defaultdict(factory)
>>> defdict = factory()
>>> defdict['one']['two']['three']['four'] = 5
>>> defdict
defaultdict(<function <lambda> at 0x103098ed8>, {'one': defaultdict(<function <lambda> at 0x103098ed8>, {'two': defaultdict(<function <lambda> at 0x103098ed8>, {'three': defaultdict(<function <lambda> at 0x103098ed8>, {'four': 5})})})})
>>> default_to_regular(defdict)
{'one': {'two': {'three': {'four': 5}}}}
你實際上要做的是腌制你的遞歸defaultdict
。 並且你不關心你是否在defaultdict
時回到了dict
或defaultdict
。
雖然有很多方法可以解決這個問題(例如,使用自己的pickle創建一個defaultdict
子類,或者使用copyreg
顯式覆蓋默認的子類),但是有一種方法可以解決這個問題。
注意嘗試時得到的錯誤:
>>> pickle.dumps(defdict)
PicklingError: Can't pickle <function <lambda> at 0x10d7f4c80>: attribute lookup <lambda> on __main__ failed
你不能腌制lambda
定義的函數,因為它們是匿名的,這意味着它們永遠不會被打開。
但實際上沒有理由這個函數需要由lambda
定義。 特別是,您甚至不希望它是匿名的,因為您明確地給它起了一個名字。 所以:
def factory(): return defaultdict(factory)
而且你已經完成了。
這是在行動:
>>> from collections import defaultdict
>>> def factory(): return defaultdict(factory)
>>> defdict = factory()
>>> defdict['one']['two']['three']['four'] = 5
>>> import pickle
>>> pickle.dumps(defdict)
b'\x80\x03ccollections\ndefaultdict\nq\x00c__main__\nfactory\nq\x01\x85q\x02Rq\x03X\x03\x00\x00\x00oneq\x04h\x00h\x01\x85q\x05Rq\x06X\x03\x00\x00\x00twoq\x07h\x00h\x01\x85q\x08Rq\tX\x05\x00\x00\x00threeq\nh\x00h\x01\x85q\x0bRq\x0cX\x04\x00\x00\x00fourq\rK\x05ssss.'
在其他情況下,沒有正當理由使用lambda
而不是def
會導致問題 - 你無法在運行時反省你的函數,你在調試器中得到更糟的回溯等等。當你想要一個固有的匿名函數時使用lambda
,或者您可以在表達式中間定義的函數,但不要使用它來保存三個字符的輸入。
一種可能性是你可以創建自己的類,可以從“defaultdict”模式切換到“vanilla”模式。 對於大型詞典,這會更快,更快。 這是一個覆蓋getitem方法並具有適當的實例變量來控制行為的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.