我试图将由字典字典组成的树状结构与包含列表的最低级字典进行交叉。以下是结构示例:
Metabolism[currentL0][currentL1][currentL2][node] = [pathway1, pathway2, pathway3]
我用这个函数来创建数据结构:
Tree = lambda: defaultdict(Tree)
Metabolism = Tree()
生成和填充数据结构的代码有效。但是,我试图使用递归生成器来横穿"树"并返回顶部键和与之关联的所有列表。生成器函数通过if isinstance
测试工作。它输入if
块打印hi
并将正确的值分配给key
,然而,它似乎跳过递归调用并打印bye
。为了测试这个,我将print key
语句放在函数的顶部,并在递归调用中将key
设置为recursive
,这样print key
语句应该打印单词{{1但是它并没有。这是生成器函数:
recursive
测试def walk_dict(d,depth=0,key=""):
print key
for k,v in d.items():
if isinstance(v, defaultdict):
print "hi"
if depth == 0:
key = k
walk_dict(v,depth+1,"recursive")
print "bye"
else:
yield key, v
语句似乎确认函数没有递归。它打印一个空行,后跟相同数量的print
和hi
s,因为有顶级字典键。以下是输出的示例:
bye
最后,这是调用生成器函数的代码:
<blank line>
hi
bye
hi
bye
hi
bye
hi
bye
hi
bye
hi
bye
答案 0 :(得分:1)
你对错误的递归函数做错了。在递归函数中,当你直接调用 - walk_dict(v,depth+1,"recursive")
时 - 它只返回生成器对象并丢弃(因为你没有对它做任何事情) - 它不会通过函数。
walk_dict()
是一个生成器函数,当你只调用walk_dict()
它只会返回生成器对象(它不会迭代它)。让我们举一个例子 -
>>> def func():
... print("Hello")
... yield 10
...
>>>
>>> func()
<generator object func at 0x006FF418>
>>> next(func())
Hello
10
正如你所看到的,只是调用生成器函数什么都不做,只有当你遍历它(或调用next())时才实际调用生成器函数。
这也是您需要在代码中执行的操作,您需要递归地遍历walk_dict()
并在每个级别生成结果。
示例 -
def walk_dict(d,depth=0,key=""):
print key
for k,v in d.items():
if isinstance(v, defaultdict):
print "hi"
if depth == 0:
key = k
for i,j in walk_dict(v,depth+1,"recursive"):
yield i, j
print "bye"
else:
yield key, v
我没有测试过上面的代码,因为我没有剩下的代码来测试它,但你可以尝试一下。
答案 1 :(得分:1)
问题是当你进行递归调用时,你没有得到结果。替换此行:
walk_dict(v,depth+1,"recursive")
这一行:
for item in walk_dict(v,depth+1,"recursive"):
yield item
如果您运行的是Python 3,则可以使用yield from
构造:
yield from item in walk_dict(v,depth+1,"recursive"):
要回答您的问题,请考虑以下调用的作用:
walk_dict(v,depth+1,"recursive")
在原始代码中,您只需调用walk_dict
,它将返回一个生成器。但是,您没有从该生成器中提取任何有用的列表并返回给您的调用者。
答案 2 :(得分:0)
一个相当基本的建议。你确定所有的缩进都是正确的吗?当标签和空格混淆时,会经常出现这种类型的错误情况。
除非您将它们配置为显示间距,否则您无法在某些编辑器中看到它。我使用Geany编辑Python代码,并使编辑器显示标签和空格,并显示选项&#39;显示空格&#39;。
如果您将Tabs编程为4个字符,这将特别令人困惑。 Python 总是考虑Tab 8空格,但编辑器可能会将其显示为4。