【发布时间】:2015-04-28 19:09:45
【问题描述】:
我只是花了几个小时在 python 中思考以下问题,但我无法弄清楚它为什么会发生。
假设我正在制作一个决策树类:
class DecisionTree:
def __init__(self, name, children = dict()):
self.name = name
self.children = children # <------- here's the problem
def add_child(self, child_name, child_tree):
self.children[child_name] = child_tree
def pprint(self, depth = 0):
for childkey in self.children:
tabs = " ".join(["\t" for x in xrange(depth)])
print tabs + 'if ' + self.name + ' is ' + str(childkey)
if (self.children[childkey].__class__.__name__ == 'DecisionTree'): # this is a tree, delve deeper
print tabs + 'and...'
child = self.children.get(childkey)
child.pprint(depth + 1 )
else:
val = self.children.get(childkey)
print tabs + 'then predict ' + str( val )
print "\n"
return ''
现在让我们构建一棵废话树,并尝试打印它:
def make_a_tree(depth = 0, counter = 0):
counter += 1
if depth > 3:
return 'bottom'
else:
tree = DecisionTree(str(depth)+str(counter))
for i in range(2):
subtree = make_a_tree(depth+1, counter)
tree.add_child(i, subtree)
return tree
foo = make_a_tree()
foo.pprint()
此代码导致无限递归循环,因为树结构(不知何故)错误地使用树的第二个节点引用自身来构建。
如果我将上面标记的行(第 5 行)更改为 tree.children = dict(),则一切正常。
我无法理解这里发生的事情。编写代码背后的意图是为“children”获取一个参数,如果没有传递,则创建一个空字典并将其用作子项。
我对 Python 还是很陌生,我正在努力让这成为一种学习体验。任何帮助将不胜感激。
【问题讨论】:
-
旁白:
child = self.children.get(childkey)/child.pprint(depth + 1 )看起来很奇怪。.get是一个字典方法,如果键不存在,则返回默认值(无,如果没有另外指定)。但如果钥匙不存在,None.pprint将不起作用;并且由于您正在循环self.children的键,我认为它必须在那里。所以self.children[childkey]就足够了,或者你可以迭代self.children.items()给出的对。 -
谢谢——那只是我拼命调试时的痕迹,寻找解决问题的方法(我一度认为我的问题出在打印功能中……不知道为什么我想使用get 而不是括号会有所帮助)。
标签: python object recursion scope