Python ООП и списки - PullRequest
       13

Python ООП и списки

4 голосов
/ 21 мая 2010

Я новичок в Python, и это ООП, и я не могу заставить его работать. Вот мой код:

class Tree:

    root = None;
    data = [];

    def __init__(self, equation):
        self.root = equation;

    def appendLeft(self, data):
        self.data.insert(0, data);

    def appendRight(self, data):
        self.data.append(data);

    def calculateLeft(self):
        result = [];
        for item in (self.getLeft()):
            if (type(item) == type(self)):
                data = item.calculateLeft();
            else:
                data = item;
            result.append(item);
        return result;

    def getLeft(self):
        return self.data;

    def getRight(self):
        data = self.data;
        data.reverse();
        return data;

tree2 = Tree("*");
tree2.appendRight(44);
tree2.appendLeft(20);

tree = Tree("+");
tree.appendRight(4);
tree.appendLeft(10);
tree.appendLeft(tree2);

print(tree.calculateLeft());

Похоже, что tree2 и tree делятся списком "данных"?

В данный момент я бы хотел, чтобы он выводил что-то вроде [[20,44], 10, 4], но когда я

tree.appendLeft(tree2) 

Я получаю RuntimeError: maximum recursion depth exceeded, а когда я даже не appendLeft(tree2), он выдает [10, 20, 44, 4] (!!!). Что мне здесь не хватает? Я использую Portable Python 3.0.1.

Спасибо

Ответы [ 3 ]

9 голосов
/ 21 мая 2010

Проблема в том, что вы объявили data как переменную класса, поэтому все экземпляры класса имеют один и тот же список. Вместо этого поместите self.data = [] в ваш __init__.

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

4 голосов
/ 21 мая 2010

Переместить корень и данные в определение __init__. В существующем состоянии они определены как атрибуты класса. Это делает их общими для всех экземпляров класса Tree. Когда вы создаете два дерева (tree и tree2), они оба совместно используют один и тот же список, доступ к которому осуществляется с помощью self.data. Чтобы каждый экземпляр имел свой собственный атрибут экземпляра, вы должны переместить объявление в функцию __init__.

def __init__(self, equation):
    self.root = equation
    self.data = []

Также используйте

        if isinstance(item,Tree):        # This is True if item is a subclass of Tree

вместо

        if (type(item) == type(self)):   # This is False if item is a subclass of Tree

и изменить

data = self.data

до

data = self.data[:]

в getRight. Когда вы говорите data = self.data, тогда имя переменной data указывает на тот же список, на который указывает self.data. Когда вы впоследствии изменяете data, вы также изменяете self.data. Чтобы изменить только data, вы должны скопировать список. self.data[:] использует нотацию срезов для возврата копии списка. Обратите внимание, что элементы self.data могут иметь значение Tree с, а self.data и self.data[:] могут содержать идентичные элементы. Я не думаю, что ваш код требует, чтобы эти элементы были скопированы, но вам нужно будет рекурсивно копировать self.data, если это так.

def getRight(self):
    data = self.data[:]
    data.reverse()
    return data
3 голосов
/ 21 мая 2010

Когда вы определяете атрибуты следующим образом:

class Tree:
    root = None
    data = []

.. этот пустой объект списка создается так, как Python определяет класс, а не при создании нового экземпляра. Это атрибут класса, а не атрибут экземпляра. Значение Tree.root - это один и тот же объект во всех случаях:

class Tree:
    root = None
    data = []

t1 = Tree()
t2 = Tree()

print id(t1.data) == id(t2.data) # is True, they are the same object

Чтобы получить ожидаемое поведение, переместите создание пустого списка в функцию __init__, которая вызывается только при создании нового экземпляра и изменяет только этот экземпляр (так как он назначается self):

class Tree:
    def __init__(self):
        self.root = None
        self.data = []

t1 = Tree()
t2 = Tree()

print id(t1.data) == id(t2.data) # False, they are different objects

Этот вопрос объясняет, почему такое поведение может быть полезным

...