указатели на связанный список в python - PullRequest
0 голосов
/ 15 января 2020

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

Однако, когда я пытаюсь обновить указатель, связанный список не обновляется. Он обновляется только при использовании оригинальной записи. Вот три проблемы, за которыми следует фрагмент кода:

pointer = self.storage[index]
pointer = pointer.next #does not work
self.storage[index] = self.storage[index].next #DOES work.
def remove(self, key):

        pair = LinkedPair(key,None)
        index = self._hash_mod(pair)

        pointer = self.storage[index]
        prev = None
        while pointer:
            if pointer.key == pair.key:
                if prev is None:  #at the beginning of the linked list, set the head to equal the next value
                    print(self.storage[index] == pointer) #true
                    self.storage[index] = self.storage[index].next
                    pointer = pointer.next
                    # pointer = pointer.next
                    break
                # self.display(pointer,prev,' pointer == pair')
                prev.next = pointer.next
                del pointer
                break
            else:
                prev = pointer
                pointer = pointer.next

            # self.display(pointer,prev,' post shifting')
            # self.storage[index] = self.storage[index].next
        return -1

1 Ответ

0 голосов
/ 15 января 2020

Переменные в python являются просто именами для объекта, и присвоение им просто меняет объект, обозначенный этим именем.

Однако при назначении элементам списка вы меняете объект, на который ссылается эта позиция в списке.

Таким образом:

pointer = self.storage[index] # 1
pointer = pointer.next  # 2
self.storage[index] = self.storage[index].next  # 3

(1) Делает pointer имя для объекта, на который ссылается storage[index]

(2) Вкл. В правой части присваивания = вы ищете атрибут name объекта, на который ссылается pointer. Это self.storage[index].name. При присвоении переменная pointer будет ссылаться на self.storage[index].name. Чтобы обновить список self.storage, вам нужно работать с самим объектом списка. В отличие от self.storage[index], на который ссылается pointer, это просто «некоторый объект». У вас даже нет способа вернуться к списку оттуда, поэтому здесь невозможно изменить список.

(3) Здесь, однако, вы меняете список self.storage, заменяя элемент в index. You could have done self.storage [index] = pointer` в этот момент, с тем же эффектом.

Конечно python работает со ссылками (или указателями) под капотом. my_list[1] = obj не выделяет место для obj, он будет хранить ссылку на него. Но локальные и глобальные переменные не являются ссылками, это имена.

В конце концов, глобальные и локальные пространства имен просто отображают имена переменных в объектах. Обычно это обычные словари. Вы можете увидеть их, позвонив globals() и locals(). Или вы можете «реализовать» назначение переменных, просто изменив этот словарь:

foo = 1
globals()["foo"] = 2
print(foo)  # --> 2

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

a = 1     # 1
b = [1]   # 2
b[0] = 2  # 3

Первые два назначения делают то же самое. Они создают (или обновляют) глобальные переменные a и b и сопоставляют их с int объектом 1 и list объектом [1] соответственно. У вас будет:

globals()
{
   ...
   "a": 1,
   "b": [1]
   ...
}

Третье назначение совершенно другое. Присвоение этого типа фактически осуществляется объектом слева. Из документов:

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

Это означает, что третье утверждение реализуется самим объектом списка. Теперь список в python содержит ссылки на объекты (он не копирует объекты). b[0], когда используется в выражении, реализуется специальным методом объекта списка и возвращает объект, на который ссылается список в позиции 0. b[0] = 2 фактически вызывает специальный метод объекта списка с индексом (0) и целевой объект (2) в качестве аргументов, и реализация списка решает, как она обновляет себя: она изменит ссылку на индекс 0 на новый объект.

Эта разница встроена в python оператор присваивания. Мне тоже понравилась полная ссылка.

Подробнее:

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