sam*_*tav 20 python collections dictionary python-2.7
使用这样的回答,我创建了一个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})})})})
Run Code Online (Sandbox Code Playgroud)
我认为这不是正确的解决方案:
import json
regdict = json.loads(json.dumps(defdict))
# {u'one': {u'two': {u'three': {u'four': 5}}}}
Run Code Online (Sandbox Code Playgroud)
此外,这个答案是不充分的,因为它没有递归嵌套的字典.
Mar*_*ers 33
你可以在树上进行递归,用defaultdictdict理解产生的dict 替换每个实例:
def default_to_regular(d):
if isinstance(d, defaultdict):
d = {k: default_to_regular(v) for k, v in d.items()}
return d
Run Code Online (Sandbox Code Playgroud)
演示:
>>> 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}}}}
Run Code Online (Sandbox Code Playgroud)
你实际上要做的是腌制你的递归defaultdict.而且你不关心你是否回来了dict或者什么defaultdict时候取消了.
虽然有很多方法可以解决这个问题(例如,创建一个defaultdict带有自己酸洗的子类,或者明确地覆盖默认的子类copyreg),但是有一种方法是琐碎的.
注意尝试时得到的错误:
>>> pickle.dumps(defdict)
PicklingError: Can't pickle <function <lambda> at 0x10d7f4c80>: attribute lookup <lambda> on __main__ failed
Run Code Online (Sandbox Code Playgroud)
你不能挑选lambda定义的函数,因为它们是匿名的,这意味着它们永远不会被打开.
但实际上没有理由需要定义此功能lambda.特别是,您甚至不希望它是匿名的,因为您明确地给它起了一个名字.所以:
def factory(): return defaultdict(factory)
Run Code Online (Sandbox Code Playgroud)
而且你已经完成了.
这是在行动:
>>> 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.'
Run Code Online (Sandbox Code Playgroud)
在其他情况下,使用lambda而不是def没有充分理由会导致问题 - 您无法在运行时自省内部功能,在调试器中获得更糟糕的回溯等.lambda当您需要固有匿名功能时使用,或者您可以在表达式中间定义的函数,但不要使用它来保存三个字符的输入.