Вопрос о связанном списке в Python, где одна переменная равна другой - PullRequest
1 голос
/ 08 апреля 2020

Рассмотрим следующий пример кода

class Node:
    def __init__(self, value = None, next = None):
        self.value = value
        self.next  = next

    def __str__(self):
        return str(self.value)

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

node5 = node1

node1.next = node2
node2.next = node3

#node5 = node1

def printList(node):
    while node:
        print(node)
        node = node.next

printList(node1)
printList(node5)

(пример взят из https://blog.csdn.net/qq_39422642/article/details/78988976). Я поставил node5 = node1 перед указанием node1.next. Однако в printList(node5) он дает тот же результат, что и printList(node1). Почему node5 сохраняет структуру связанного списка, даже если значение задано до установления sh связанного списка?

Если я использую нормальные переменные

a = 3
b = a
a = 2
print(a,b)

, результат равен 2,3. Код b=a не будет зависеть от кода после него, в отличие от примера связанного списка в первом блоке. Спасибо!

1 Ответ

1 голос
/ 08 апреля 2020

Поскольку в Python переменные хранят ссылки (не значения). Оператор node5 = node1 фактически заставляет node5 указывать на объект. node1 также указывает на тот же объект. Если вы внесете изменения в этот объект с помощью node1 или node5 и напечатаете результаты с помощью node1 или node5, он напечатает тот же результат.

Другое поведение, которым вы были наблюдение с использованием int объясняется тем, что int является неизменным в Python. Если вы измените значение объекта, python создаст другой объект, сохранит в нем новое значение и обновит b, чтобы указать на этот объект (b = a). После этого оператора a будет по-прежнему указывать на старый объект, имеющий значение 2. Если вы попробуете второй код с любым из неизменяемых в Python, вы получите тот же результат.

Если вы хотите скопировать узел 1 в узел 5, используйте deepcopy :

import copy

class Node:
    def __init__(self, value = None, next = None):
        self.value = value
        self.next  = next

    def __str__(self):
        return str(self.value)

node1 = Node(1)
node2 = Node(2)
node3 = Node(3)

node4 = node1
node5 = copy.deepcopy(node1)

node1.next = node2
node2.next = node3


def printList(node):
    while node:
        print(node, end=" ")
        node = node.next
    print("")

print("Node1 Id", id(node1), end=" ")
printList(node1)
print("Node4 Id", id(node4), end=" ")
printList(node4)
print("Node5 Id", id(node5), end=" ")
printList(node5)

Выходы:

Node1 Id 140465951784072 1 2 3
Node4 Id 140465951784072 1 2 3
Node5 Id 140465951810560 1

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

Добавлено id () в моем ответе, как предложено @ user3159253. Вы можете видеть, что id(), возвращаемые node1 и node4, одинаковы. Это означает, что они действительно указывают на один и тот же объект и любое изменение, сделанное с использованием любой из переменных (node4 или node1), это изменит один и тот же объект и, следовательно, вы получите тот же результат, если вы печатаете с использованием либо node1, либо node4 .

Однако, если вы попробуете свой второй код с id():

a = 2
b = a

print("Id of a", id(a), "Value of a", a)
print("Id of b", id(b), "Value of b", b)

a = 5

print("Id of a", id(a), "Value of a", a)
print("Id of b", id(b), "Value of b", b)

Вывод:

Id of a 10914528 Value of a 2
Id of b 10914528 Value of b 2
Id of a 10914624 Value of a 5
Id of b 10914528 Value of b 2

Как вы можете видеть после назначения b = a , a и b указывали на один и тот же объект, но как только вы переназначили значение a на 5, python создали другой объект (и, следовательно, id () вернул другое значение) и изменили a указать на этот объект, имеющий значение 5. Это произошло потому, что int неизменны в Python.

...