Записи списка Python переопределяются последней добавленной записью - PullRequest
0 голосов
/ 05 марта 2010

У меня есть этот код:

def __parse(self):        
    for line in self.lines:
        r = Record(line)
        self.records[len(self.records):] = [r]
        print self.records[len(self.records)-1].getValue() # Works fine!
    print self.record[0].getValue() # Gives the same as
    print self.record[1].getValue() # as
    # ... and so on ...
    print self.record[len(self.record)-1].getValue()

Теперь, что он должен делать, это делать записи из строк текста.Но когда я получаю доступ к этому списку после завершения цикла for, все записи дают одинаковые результаты для методов, которые я вызываю для них.Когда я получаю доступ к записи внутри цикла for сразу после ее добавления, она становится правильной, поэтому запись init не может быть ошибкой.Нет, абсолютно уверен, что линии, которые я вставил, разные!Кто-нибудь знает, почему это происходит?Помощь будет очень ценится!

Ответы [ 6 ]

1 голос
/ 05 марта 2010

Запись класса нарушена. Вы используете переменную класса (Record.record) вместо атрибута экземпляра. Переменная класса одна для всех экземпляров, и вы хотите разные self.record для каждого экземпляра.

Переместить:

record = {}
line = ""

строк в конструкторе (с отступом def __init__(self,line):)

1 голос
/ 05 марта 2010

Ахуе, у вас есть изменяемые объекты в пространстве имен класса shared - очень распространенное заблуждение при запуске с python. Переместите инициализацию records = [] в CsvSet в ее функцию __init__ и переместите record = {} в Record __init__ функцию. Должно выглядеть так:

class Record:
    def __init__(self,lines):
        self.record = {}
        self.__parse()

class CsvSet:
    def __init__(self,lines):
        self.records = []
        self.__parse()

Когда вы объявляете непостоянную переменную в области классов, она распределяется между всеми экземплярами этих классов, а не создается для каждого экземпляра. Перемещая инициализацию в метод экземпляра (в данном случае __init__), вы создаете новые изменяемые хранилища для каждого экземпляра, что вы и планировали.

1 голос
/ 05 марта 2010

Это все еще происходит, если вы замените его следующим:

self.record = [Record(l) for l in self.lines]

РЕДАКТИРОВАТЬ:

Что-то должно быть неправильным в Record поскольку код там работает, даже если опытный кодер плачет, когда читает его.

1 голос
/ 05 марта 2010

Вы не добавляете к self.records; Вы всегда перезаписываете это.

Использование:

self.records.append(r)

вместо.

Редактировать : Неважно. Смотрите комментарий Игнасио Васкеса-Абрамса. Я бы удалил этот ответ, если бы не это.

0 голосов
/ 05 марта 2010

Хорошо, поэтому я выложу код для класса Record для пояснения.

Запись класса:

record = {}
line = ""

def __init__(self,line):
    self.line = line 
    self.__parse()

def __parse(self):
    fieldnames = ['from','to','value','error']
    fields = self.line.split(',')

    c = 0
    for field in fields:
        self.record[fieldnames[c]] = field.strip()
        c+=1

    self.record['from'] = datetime.datetime.strptime(self.record['from'],"%Y-%m-%d")
    self.record['to'] = datetime.datetime.strptime(self.record['to'],"%Y-%m-%d")

класс CsvSet:

records = []

def __init__(self,lines):
    self.__parse()

def __parse(self):        
    for line in self.lines:
        self.records.append(Record(line))

Метод __parse в CsvSet теперь такой, каким он был в начале. Я изменил, если по причинам отладки, но результат тот же. И Игнасио, ты прав, я начал с Python только 2 недели назад ...

0 голосов
/ 05 марта 2010

Класс Record не работает, вы всегда возвращаете один и тот же объект.

Не видя код для записи, невозможно угадать

Возможно, вы используете список или dict в качестве параметра по умолчанию для __init__ и возвращаете его с getValue().

Другая возможность состоит в том, что getValue() возвращает атрибут класса, а не атрибут экземпляра

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