访问从类级别定义的数组属性时出现递归错误

时间:2016-11-17 01:31:17

标签: python

所以这是我的代码,我想要制作一个简单的节点树:

class Node(object):
    child = []
    def __init__(self,id):
            self.id =id
    def addChild(self,child):
            self.child.append(child)
    def printChildOnwards(self):
            yield self.id
            for x in self.child:
                    yield from x.printChildOnwards()


firstChild = Node('1')
secondChild = Node('2')
thirdChild = Node('3')
fourthChild = Node('4')

firstChild.addChild(secondChild)
firstChild.addChild(thirdChild)


for x in firstChild.printChildOnwards():
    print(x)

我已经通过self访问了已定义的类级属性,以确保我访问自己的版本。

输出: 1 2 2 2 2 ... then recursion error max depth

虽然我可以在__init__内简单地定义它,但是它有效 self.child = []

输出:1 2 3

这种行为背后的原因是什么?为什么我需要将其包含在__init__

1 个答案:

答案 0 :(得分:1)

在您的初始示例中:

class Node(object):

    child = []

    def __init__(self, id):
        self.id = id

child属性是Node类的类级别属性,这意味着Node的每个实例都将共享该对象,因此每次迭代都会printChildOnwards呼叫只会从同一列表中继续打印。正如您所发现的那样,在__init__方法中定义它会起作用,因为它为每个实例创建了一个实例级child属性,因此它们现在都是唯一的,并且不会导致迭代通过相同的共享列表孩子们。

您可以使用id函数轻松验证任何对象的标识(内存地址)。有了它,您可以自己看到使用此示例的子属性是相同的:

>>> n1 = Node(1)
>>> n2 = Node(2)
>>> id(n1.child)
139928077828744
>>> id(n2.child)
139928077828744

将其更改回您修复的版本:

class Node(object):             
    def __init__(self, id):     
        self.child = []              
        self.id = id            

再次使用id功能再次验证并发现它们不同。

>>> n1 = Node(1)                                               
>>> n2 = Node(2)                                                               
>>> id(n1.child)
139928077829192
>>> id(n2.child)
139928077828936