我只是花了几个小时的时间在思考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还很陌生,我正在努力让这成为一次学习的经历。任何帮助都将不胜感激。你知道吗
问题是函数的默认参数(并且
__init__()
不是免除的)只创建一次。换句话说,每次创建一个新的DecisionTree
时,您都在重用相同的dict
对象。你知道吗你需要做的是:
为了解决您的问题,我建议将默认参数children初始化为None,并使用如下行: 自我保护儿童=children或dict()
问题是,在Python中,函数参数是通过引用传递的,具有可变值(字典也是可变的)的默认参数是在函数定义时(仅一次)计算的,而不是在每次调用函数时计算的,结果是每次调用函数dict()时都会返回相同的引用。 常见的Python陷阱。你知道吗
相关问题 更多 >
编程相关推荐