В дереве узлов parent.addChild(self) добавляет self к self

#python #nodes

#python #узлы

Вопрос:

Я создаю простое дерево узлов на python. Но когда мой конструктор пытается добавить текущий узел в качестве дочернего элемента данного родительского элемента, текущий узел также добавляет себя в качестве дочернего элемента самого себя.

Вот мой метод конструктора (и создание children ):

 children = []

def __init__(self, parent=None, tag="[ROOT]", attrs=None):
        self.parent = parent
        self.tag = tag
        self.attrs = attrs
        print "n", "self:%s ... children:%s" % (self.tag, self.children)
        if parent != None:
            parent.addChild(self)
        print "self:%s ... children:%s" % (self.tag, self.children)
  

Вот мой метод addChild в том же классе (который должен вызываться для родительского элемента, а не для узла, который в настоящее время создается):

 def addChild(self, child):
        self.children.append(child)
  

Вот результат:

 foo []
foo [foo]
  

Две строки вывода должны быть одинаковыми, потому что строка кода между ними должна влиять только на родительский узел, а не на узел, находящийся в стадии разработки.

Что я делаю не так?

Комментарии:

1. Где self.children создается? Ваш __init__ метод, похоже, не инициализирует его.

2. Откуда берется этот вывод? Это не соответствует этим print заявлениям.

3. @Tamas, я изменил приведенный выше код, чтобы указать, где self.children создается.

4. @John Kugelman, я определил __repr__(self) значение return self.tag , поэтому вывод, который я визуализировал, фактически соответствует выводам инструкций print в __init__ коде.

Ответ №1:

Когда вы инициализируете дочерние элементы на уровне класса, каждый экземпляр вашего класса в конечном итоге совместно использует один и тот же объект list.

 >>> class C:
...  children = []
... 
>>> a = C()
>>> b = C()
>>> id(a.children)
144349644
>>> id(b.children)
144349644
  

Попробуйте вместо этого инициализировать его в своем конструкторе:

 def __init__(self, parent=None, tag="[ROOT]", attrs=None):
    self.children = []
  

Ответ №2:

Я подозреваю, children что он каким-то образом является общим для всех ваших объектов узла; мы не можем видеть объявление, поэтому я не могу точно сказать, что вы делаете неправильно.