id(i) == id(k) # False (as these are two separate objects)
Правильно.
id(i[0]) == id (k[0]) # True (as the reference the same location, right?)
Правильно.
i[0] = 100
id(i[0]) == id (k[0]) # False (why did that value in that loc change?)
Он изменился, потому что вы изменили его в предыдущей строке .i[0]
был , указывая 10
, но вы изменили его, указав на 100
.Следовательно, i[0]
и k[0]
теперь больше не указывают на одно и то же место.
Указатели (ссылки) в одну сторону .10
не знает, что на это указывает.Также не 100
.Это просто места в памяти.Поэтому, если вы измените , где первый элемент i
указывает на, k
не волнует (поскольку k
и i
не та же ссылка),Первый элемент k
все еще указывает на то, на что он всегда указывал.
id(i[:]) == id (k[:]) # True (why is this still true if an element just changed?)
Этот элемент немного более тонкий, но учтите, что:
>>> id([1,2,3,4,5]) == id([1,2,3])
True
, тогда как
>>> x = [1,2,3,4,5]
>>> y = [1,2,3]
>>> id(x) == id(y)
False
Это связано с некоторыми тонкостями сборки мусора и идентификатора, и здесь подробно рассматривается: Безымянный объект Python имеет одинаковый идентификатор .
Короче говоря, когда вы говорите id([1,2,3,4,5]) == id([1,2,3])
, первое, что происходит, мы создаем [1,2,3,4,5]
.Затем мы берем, где он находится в памяти с вызовом id
.Однако [1,2,3,4,5]
является анонимным, и сборщик мусора немедленно возвращает его.Затем мы создаем еще один анонимный объект, [1,2,3]
, и CPython решает, что он должен идти в месте, которое он только что очистил.[1,2,3]
также немедленно удаляется и очищается.Если вы сохраните ссылки, однако, GC не сможет помешать, и тогда ссылки будут другими.
Пример изменяемых файлов
То же самое происходит с изменяемыми объектами, если вы переназначаете их.Вот пример:
>>> import copy
>>> a = [ [1,2,3], [4,5,6], [7,8,9] ]
>>> b = copy.copy(a)
>>> a[0].append(123)
>>> b[0]
[1, 2, 3, 123]
>>> a
[[1, 2, 3, 123], [4, 5, 6], [7, 8, 9]]
>>> b
[[1, 2, 3, 123], [4, 5, 6], [7, 8, 9]]
>>> a[0] = [123]
>>> b[0]
[1, 2, 3, 123]
>>> a
[[123], [4, 5, 6], [7, 8, 9]]
>>> b
[[1, 2, 3, 123], [4, 5, 6], [7, 8, 9]]
Разница в том, что когда вы говорите a[0].append(123)
, мы модифицируем все, на что указывает a[0]
.Случается, что b[0]
указывает на один и тот же объект (a[0]
и b[0]
являются ссылками на тот же объект).
Но если вы указываете a[0]
для нового объекта (через присваивание, как в a[0] = [123]
), тогда b[0]
и a[0]
больше не указывают на то же место.