Python: когда две переменные указывают на один и тот же объект в памяти?

вот пример:

l = [1, 5, 9, 3]
h = l

h[0], h[2] = h[2], h[0]

print(h) # [9, 5, 1, 3]
print(l) # [9, 5, 1, 3]

h = h*2
print(h) # [9, 5, 1, 3, 9, 5, 1, 3]
print(l) # [9, 5, 1, 3]

мое понимание было, что звонить параметр h = l будет просто указать h на том же элементе в памяти, что l указывал на. Так почему же в последних 3 строках, h и l не дают те же результаты?

6 ответов


задание делает h укажите на тот же элемент, что и l. Тем не менее, он не постоянно сваривает два. При изменении h С h = h * 2, вы говорите Python построить удвоенную версию в другом месте в памяти, а затем сделать h укажите на удвоенную версию. Вы не давали никаких инструкций, чтобы изменить l; это все еще указывает на исходный элемент.


Это довольно просто проверить, выполните этот простой тест:

l = [1, 5, 9, 3]
h = l

h[0], h[2] = h[2], h[0]

print(h)  # [9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

print id(h), id(l)
h = h * 2
print id(h), id(l)

print(h)  # [9, 5, 1, 3, 9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

как вы можете видеть из-за линии h = h * 2, идентификатор h был изменен

Почему это? Когда вы используете * оператор создает новый список (новая память). В вашем случае этот новый список присваивается старой ссылке h, поэтому вы можете видеть, что id отличается после h = h * 2

если вы хотите узнать больше об этом предмете, убедитесь, что вы смотрите на сведения Модель ссылка.


h = h * 2 назначает h к новому объекту списка.

вы, вероятно, хотите изменить h на месте:

h *= 2
print(h) # [9, 5, 1, 3, 9, 5, 1, 3]
print(l) # [9, 5, 1, 3, 9, 5, 1, 3]

в любое время, когда вы назначаете переменной, ее идентификатор (адрес памяти) обычно меняется - единственная причина, по которой он не изменится, заключается в том, что вы назначили ему значение, которое он уже держал. Итак, ваше заявление h = h * 2 заставил h стать совершенно новым объектом - тем, значение которого было основано на предыдущем значении h, но это не имеет отношения к его идентичности.


это сложно, но когда вы умножаете список, вы создаете новый список.

l = [1, 5, 9, 3]
h = l

'l ' и' h ' теперь ссылаются на один и тот же список в памяти.

h[0], h[2] = h[2], h[0]

print(h)  # [9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

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

h = h * 2

print(h)  # [9, 5, 1, 3, 9, 5, 1, 3]
print(l)  # [9, 5, 1, 3]

при умножении h * 2, вы создаете новый список, так что теперь только l будет исходный объект списка.

>>> l = [1, 5, 9, 3]
>>> h = l
>>> id(h) == id(l)
True
>>> id(h)
139753623282464
>>> h = h * 2
>>> id(h) == id(l)
False
>>> id(h)
139753624022264

видел, как id of h изменения после умножения? The * оператор создает новый список, в отличие от других список операций, таких как append(), которые изменяют текущий список.

>>> h.append(1000)
>>> id(h)
139753623282464    # same as above!

надеюсь, что это помогает!


import numpy as np
print np.may_share_memory(l,k)

помогает подтвердить, что две переменные l и k имеют одинаковую память