Python 2.7:奇怪的构造函数行为:更改错误的字段

时间:2013-02-21 15:21:27

标签: python python-2.7

在此代码中:

# coding=utf-8


def print_tree(node, tree=0):
    print(u"|---" * tree + u"-> %s" % node)
    for kid in node.children:
        print_tree(kid, tree + 1)


class Person(object):
    parent = None
    first_name = None
    last_name = None
    children = []

    def __str__(self):
        return '%s %s' % (self.first_name, self.last_name)

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

    def __init__(self, first_name, last_name, parent=None):
        if parent is not None:
            if not isinstance(parent, Person):
                raise AttributeError('`parent` is not `Person` type!')
            self.parent = parent
            self.parent.children.append(self)
        self.first_name = first_name
        self.last_name = last_name
        #self.children = []


root = Person('Alan', 'Smith')
p1 = Person('Barbara', 'Smith', root)
p2 = Person('Basia', 'Smith', root)
p3 = Person('Bary', 'Smith', root)

print_tree(root)

如果我从#self.children = []移除评论示例工作正常。但我不明白为什么我必须添加这一行?

在调试器中,我发现行self.parent.children.append(self)也将self添加到self.children

为什么?

4 个答案:

答案 0 :(得分:2)

children是一个类属性,您希望它是一个实例属性。您应该完全从类范围中删除children=[],并只在__init__方法中保留一个。{/ p>

答案 1 :(得分:1)

在python中,当你在类级别声明一个属性时,它会使它成为一个类属性(在类的所有实例之间共享)。在您的情况下,您需要实例属性。必须在构造函数(您的self.children = [])中创建实例属性。

答案 2 :(得分:0)

你遇到了问题,因为在你的代码中childrenclass variable(当你在类级别而不是在实例级别上访问它时会引用它),而不是{{1} (对每个实例都是唯一的)。

所以你必须添加如下内容:

instance variable

每次self.children = [] __init__的实例。

答案 3 :(得分:0)

您正在引用对象实例中的子项,因此您不能仅将其保留在Class范围/图层中。因此,您需要self.children = [],否则您不是指实例的子项而是指类'。 (后者的语法是Person.children