我意识到这是一个老问题,但我只是在寻找一个简单,干净的方式来走嵌套的听写,这是最近的事情,我有限的搜索已经想出。如果你想要的不仅仅是文件名,那么oadams的答案还不够有用,spicavigo的答案看起来很复杂。
最后我只滚动了自己的文件,其行为类似于os.walk处理目录的方式,只是它返回了所有键/值信息。
它返回一个迭代器,对于嵌套dict的“树”中的每个目录,迭代器返回(路径、子dict、值),其中:path是指向dict的路径
sub dict是这个dict中每个sub dict的(key,dict)对的元组
values是这个dict中每个(非dict)项的(key,value)对的元组
def walk(d):
'''
Walk a tree (nested dicts).
For each 'path', or dict, in the tree, returns a 3-tuple containing:
(path, sub-dicts, values)
where:
* path is the path to the dict
* sub-dicts is a tuple of (key,dict) pairs for each sub-dict in this dict
* values is a tuple of (key,value) pairs for each (non-dict) item in this dict
'''
# nested dict keys
nested_keys = tuple(k for k in d.keys() if isinstance(d[k],dict))
# key/value pairs for non-dicts
items = tuple((k,d[k]) for k in d.keys() if k not in nested_keys)
# return path, key/sub-dict pairs, and key/value pairs
yield ('/', [(k,d[k]) for k in nested_keys], items)
# recurse each subdict
for k in nested_keys:
for res in walk(d[k]):
# for each result, stick key in path and pass on
res = ('/%s' % k + res[0], res[1], res[2])
yield res
下面是我用来测试它的代码,尽管里面有一些其他不相关的(但很整洁的)东西:import simplejson as json
from collections import defaultdict
# see https://gist.github.com/2012250
tree = lambda: defaultdict(tree)
def walk(d):
'''
Walk a tree (nested dicts).
For each 'path', or dict, in the tree, returns a 3-tuple containing:
(path, sub-dicts, values)
where:
* path is the path to the dict
* sub-dicts is a tuple of (key,dict) pairs for each sub-dict in this dict
* values is a tuple of (key,value) pairs for each (non-dict) item in this dict
'''
# nested dict keys
nested_keys = tuple(k for k in d.keys() if isinstance(d[k],dict))
# key/value pairs for non-dicts
items = tuple((k,d[k]) for k in d.keys() if k not in nested_keys)
# return path, key/sub-dict pairs, and key/value pairs
yield ('/', [(k,d[k]) for k in nested_keys], items)
# recurse each subdict
for k in nested_keys:
for res in walk(d[k]):
# for each result, stick key in path and pass on
res = ('/%s' % k + res[0], res[1], res[2])
yield res
# use fancy tree to store arbitrary nested paths/values
mem = tree()
root = mem['SomeRootDirectory']
root['foo.txt'] = None
root['bar.txt'] = None
root['Stories']['Horror']['rickscott.txt'] = None
root['Stories']['Horror']['Trash']['notscary.txt'] = None
root['Stories']['Cyberpunk']
root['Poems']['doyoureadme.txt'] = None
# convert to json string
s = json.dumps(mem, indent=2)
#print mem
print s
# json.loads converts to nested dicts, need to walk them
for (path, dicts, items) in walk(json.loads(s)):
# this will print every path
print '[%s]' % path
for key,val in items:
# this will print every key,value pair (skips empty paths)
print '%s = %s' % (path+key,val)
输出如下:{
"SomeRootDirectory": {
"foo.txt": null,
"Stories": {
"Horror": {
"rickscott.txt": null,
"Trash": {
"notscary.txt": null
}
},
"Cyberpunk": {}
},
"Poems": {
"doyoureadme.txt": null
},
"bar.txt": null
}
}
[/]
[/SomeRootDirectory/]
/SomeRootDirectory/foo.txt = None
/SomeRootDirectory/bar.txt = None
[/SomeRootDirectory/Stories/]
[/SomeRootDirectory/Stories/Horror/]
/SomeRootDirectory/Stories/Horror/rickscott.txt = None
[/SomeRootDirectory/Stories/Horror/Trash/]
/SomeRootDirectory/Stories/Horror/Trash/notscary.txt = None
[/SomeRootDirectory/Stories/Cyberpunk/]
[/SomeRootDirectory/Poems/]
/SomeRootDirectory/Poems/doyoureadme.txt = None