Python堆栈损坏?
我对python(但不是编程)比较陌生,无法解释以下行为。似乎来自一个对象(“子对象”)的变量(在我的示例中是列表“子对象”)正在被完全不同的对象(“节点”)中该变量的值覆盖。为了提供一些上下文,我尝试创建一个简单的节点类,以便在树结构中使用。该节点具有子节点和父节点(所有其他节点) 我不明白为什么child.children会得到与node.children相同的值。它们是否以某种方式引用了相同的数据?为什么?代码和输出如下:Python堆栈损坏?,python,Python,我对python(但不是编程)比较陌生,无法解释以下行为。似乎来自一个对象(“子对象”)的变量(在我的示例中是列表“子对象”)正在被完全不同的对象(“节点”)中该变量的值覆盖。为了提供一些上下文,我尝试创建一个简单的节点类,以便在树结构中使用。该节点具有子节点和父节点(所有其他节点) 我不明白为什么child.children会得到与node.children相同的值。它们是否以某种方式引用了相同的数据?为什么?代码和输出如下: class Node: children = []
class Node:
children = []
parent = 0
visited = 0
cost = 0
position = (0, 0)
leaf = 0
def __init__(self, parent, pos):
self.parent = parent
self.position = pos
def addChild(self, node):
self.children += [node]
node = Node(0, (0,0))
child = Node(node, (3,2))
node.addChild(child)
print "node: ",
print node
print "node.childen: ",
print node.children
print "child: ",
print child
print "child.children",
print child.children
输出:
node: <__main__.Node instance at 0x414b20>
node.childen: [<__main__.Node instance at 0x414b48>]
child: <__main__.Node instance at 0x414b48>
child.children [<__main__.Node instance at 0x414b48>]
节点:
node.childen:[]
儿童:
child.children[]
如您所见,node.children和child.children具有相同的值(包含child的列表),即使我只更新了node.children。谢谢你的帮助 您已将“children”作为类属性,这意味着它在该类的所有对象之间共享 相反,在类的init方法中初始化它
def __init__(self):
self.children = []
...
children
变量已声明为类级变量,因此它在节点的所有实例中共享。您需要通过在初始值设定项中设置它来将其声明为实例变量
class Node:
#children = [] # not here...
parent = 0 # might want to rethink where you initialize these
visited = 0
cost = 0
position = (0, 0)
leaf = 0
def __init__(self, parent, pos):
self.parent = parent
self.position = pos
self.children = [] # ...but here
def addChild(self, node):
self.children += [node]
这实际上与可变默认gotcha的效果相同。变量本身不是共享的,但其值是对可变内容的引用。因此,这些类级整数是安全的,但由于列表是可变的,因此添加到列表后会修改原始对象。@tobyodavies它是“共享的”,甚至可以将其视为对象的一部分。每个节点
实例都可以访问一个节点.parent
值,因为它属于类而不是单个实例。只是写入节点。parent
会创建一个单独的值,该值是实例的一部分,并隐藏节点中的节点。parent
在节点中(但它仍然可以作为子级。parent
访问)。所有这些变量都应该在初始化中设置,而不是在类级别设置,因为它们在逻辑上是单个实例的一部分。Python不是Java(或C++或C.java):Python遵循的是在“代码>类< <代码>块内直接声明的一致规则……属于类(因此不属于实例)。@KarlKnechtel correct---只有一个对象,但有n+1
对它的单独引用,每个节点实例一个,类本身一个。这是最正确的按值复制描述,其中值是对对象的引用(与python和java以及许多其他语言的调用约定相同)。我的观点是引用被复制到实例--Klass.x
与Klass().x
as不是同一个变量,尽管它们可能是对同一对象的单独引用(默认情况下也是如此)。我试图避免评论“应该”初始化什么的风格问题。