2015-04-23 2 views
2

Я пишу класс Python на основе списка. Конструктор создает список на основе двух других списков, которые передаются как параметры. Логика примерно: скопировать список A в новый экземпляр, затем перебрать список B, добавить некоторые записи и использовать другие для изменения записей из списка A.Конструктор класса Python возвращает пустое значение

У меня есть две версии конструктора. В первом списке A и списке B обрабатывались контурами. Тогда я решил стать умным; Я использовал понимание, чтобы заменить цикл, который добавляет список A в новый экземпляр.

Первая версия конструктора отлично работает. Вторая версия возвращает пустой список, хотя я могу посмотреть на значение self в отладчике непосредственно перед концом конструктора и см., что это правильно.

Почему это происходит, и что я могу сделать, чтобы вторая версия работала?

Вот код, который делает вторую версию misbehave. Он копирует список A в новый экземпляр, затем выполняет итерацию по экземпляру для обновления данных в словаре, который представляет элементы в списке B. ba - это список A; getkey - это функция (переданная как параметр), которая выводит ключ словаря из элемента списка; _dictb представляет собой словарь, который содержит элемент для каждого элемента в списке B.

self = [ [bae,None] for bae in ba ] # Copy list A to self 
for n in xrange(0,len(self)) :  # Iterate over list B 
    _key = getkey(self[n][0]) 
    if _dictb.has_key(_key) : 
     _dictb[_key] = n 

В первом варианте, который работает, приведенный выше код заменяется этим; операции, выполняемые и значения переменных одинаковы:

for bae in ba : 
    _key = getkey(bae) 
    if _dictb.has_key(_key) : 
     _dictb[_key] = len(self) 
    self.append([bae,None]) 
+0

См. Http://stackoverflow.com/questions/1015592/why-is-self-in-python-objects-immutable –

ответ

2

Если вы к югу причислять к list вы не хотите, чтобы повторно назначить объект self в конструкторе. Это не повлияет на внутреннее содержимое самого списка, но заменит ссылку self на то, что вы только что создали.

Другими словами, он не будет иметь желаемого эффекта, который вы после.

Вместо сделать что-то вроде этого:

class MyList(list): 

    def __init__(self, xs): 
     super(MyList, self).__init__() 

     for x in xs: # Assign all values of xs to the list object ``self`` 
      self.append(x) 
3

Я предполагаю, что вы на самом деле говорим о конструкторах Python здесь и по какой-то странной причине, опущено определение класса и заявление. В «второй версии», которая является первым фрагментом кода, который вы указали, ваша первая строка присваивает список локальной переменной с именем «self». Это НЕ заменяет объект, создаваемый другим объектом. Вещей, возвращаемой конструктором, является новый объект, а не переменная self.

Решение: не назначайте себя. Когда-либо. Даже не думай об этом.

Также вы не можете использовать понимание списка для создания подкласса списка, только экземпляр списка. Ваша «первая версия» (второй фрагмент кода) работает, и в этом нет ничего плохого.

Кроме того, вы должны заменить «_dictb.has_key (ключ)» на «ключ в _dictb».

Смежные вопросы