for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
我正在尝试遍历字典并打印出值不是嵌套字典的所有键值对 . 如果值是字典,我想进入它并打印出其键值对...等 . 有帮助吗?
编辑
这个怎么样?它仍然只打印一件事 .
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
完整测试案例
字典:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
结果:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
11 回答
正如Niklas所说,你需要递归,即你想定义一个函数来打印你的dict,如果值是一个dict,你想用这个新的dict来调用你的打印函数 .
就像是 :
或者对于Python 3以上版本:
由于
dict
是可迭代的,因此您可以将经典nested container iterable formula应用于此问题,只需进行一些小的更改 . 这是一个Python 2版本(见下面的3):测试:
在Python 2中,有可能创建一个自定义
Mapping
,它符合Mapping
但不包含iteritems
,在这种情况下,这将失败 . 文档并未表明Mapping
需要iteritems
;另一方面,source给Mapping
类型一个iteritems
方法 . 因此,对于自定义Mappings
,显式继承collections.Mapping
以防万一 .在Python 3中,有许多改进 . 从Python 3.3开始,抽象基类存在于
collections.abc
中 . 它们仍然保留在collections
中以便向后兼容,但是在一个命名空间中将抽象基类放在一起会更好 . 所以这从collections
进口abc
. Python 3.3还添加了yield from
,它专为这些情况而设计 . 这不是空的句法糖;它可能导致faster code与coroutines进行更明智的互动 .替代迭代解决方案:
如果您编写自己的递归实现或使用堆栈的迭代等效项,则有 potential problems . 看这个例子:
在通常意义上,嵌套字典将是一个像数据结构一样的n-nary树 . 但定义 doesn't exclude 交叉边甚至后边的可能性(因此不再是树) . 例如,这里key2.2从key1保持字典,key2.3指向整个字典(后边缘/循环) . 当存在后沿(循环)时,堆栈/递归将无限运行 .
如果您使用此实现从 Scharron 打印此字典
你会看到这个错误:
senderle 的实施情况也是如此 .
类似地,您从 Fred Foo 获得此实现的无限循环:
但是,Python实际上会检测嵌套字典中的循环:
""是检测到循环的地方 .
根据 Moondra 的要求,这是一种避免循环(DFS)的方法:
我编写的版本略有不同,可以跟踪到达目的地的密钥
在您的数据上,它将打印出来
它也很容易修改它来跟踪前缀作为键的元组而不是字符串,如果你需要它那样 .
这是pythonic方式来做到这一点 . 此功能允许您循环遍历所有级别中的键值对 . 它不会将整个事物保存到内存中,而是在循环时遍历字典
打印
迭代解决方案作为替代方案:
基于Scharron解决方案的列表的替代解决方案
这是Fred Foo对Python 2的回答的修改版本 . 在原始响应中,只输出最深层次的嵌套 . 如果将键输出为列表,则可以保留所有级别的键,但要引用它们,则需要引用列表列表 .
这是功能:
要引用密钥:
对于三级字典 .
你需要知道访问多个密钥之前的级别数量,级别的数量应该是不变的(在迭代值时可以添加一小部分脚本来检查嵌套级别的数量,但我还没有但看着这个) .
我发现这种方法更灵活一些,在这里你只需要提供发出键,值对的生成器函数,并且可以很容易地扩展到迭代列表 .
然后你可以编写自己的
myprint
函数,然后打印这些键值对 .一个测试:
输出:
我在Python 3.6上测试了这个 .
我使用以下代码打印嵌套字典的所有值,考虑到值可能是包含字典的列表 . 在将JSON文件解析为字典并需要快速检查其中的任何值是否为_1756833时,这对我很有用 .
输出: