Неизменяемый объект в python

Я вижу статью о неизменяемом объекте.

Он говорит, когда:
variable = immutable
Как назначить неизменяемую переменную.

например
a = b # b is a immutable
Он говорит, что в этом случае a относится к a copy of b , а не reference to b . Если b является mutable , a wiil a reference to b

так:

 a = 10 b = a a =20 print (b) #b still is 10 

но в этом случае:

 a = 10 b = 10 a is b # return True print id(10) print id(a) print id(b) # id(a) == id(b) == id(10) 

если a является копией 10 , а b также является копией 10 , почему id(a) == id(b) == id(10)?

4 Solutions collect form web for “Неизменяемый объект в python”

Хотя эта статья может быть правильной для некоторых языков, это неправильно для Python.

Когда вы выполняете любое обычное задание в Python :

 some_name = some_name_or_object 

Вы ничего не делаете. Вы просто указываете имя на объекте с правой стороны задания.

Мутируемость не имеет значения.

Более конкретно, причина:

 a = 10 b = 10 a is b 

True , то есть 10 интернированных – это означает, что Python хранит один 10 в памяти, и все, что установлено на 10 пунктов, соответствует тому же 10 .

Если вы это сделаете

 a = object() b = object() a is b 

Вы получите False , но

 a = object() b = a a is b 

все равно будет True .

«Простые» неизменяемые литералы (и, в частности, целые числа от -1 до 255) интернированы , а это значит, что даже если они связаны с разными именами, они все равно будут одним и тем же объектом.

 >>> a = 'foo' >>> b = 'foo' >>> a is b True 

Поскольку интернирование уже объяснено, я буду рассматривать только изменяемый / неизменный материал:

Как назначить неизменяемую переменную.

Говоря о том, что происходит на самом деле, я бы не выбрал эту формулировку.

У нас есть объекты (материал, который живет в памяти) и означает доступ к этим объектам: имена (или переменные), они привязаны к объекту в ссылке. (Вы могли бы указать точку на объекты)

Имена / переменные независимы друг от друга, они могут быть связаны с одним и тем же объектом или с разными. Перемещение одной такой переменной не затрагивает других.

Нет такой вещи, как передача по значению или передача по ссылке. В Python вы всегда передаете / назначаете «по объекту». При назначении или передаче переменной функции Python никогда не создает копию, она всегда передает / присваивает тот же самый объект, который у вас уже есть.

Теперь, когда вы пытаетесь изменить неизменяемый объект, что происходит? Как уже было сказано, объект неизменен, поэтому вместо этого происходит следующее: Python создает модифицированную копию .

Что касается вашего примера:

 a = 10 b = a a =20 print (b) #b still is 10 

Это не связано с изменчивостью. В первой строке вы привязываете объект int со значением 10 к имени a . Во второй строке вы привязываете объект, на который указывает a на имя b .

В третьей строке вы привязываете объект int со значением 20 к имени a , которое не меняет то, к чему привязано имя b !

Он говорит, что в этом случае a относится к копии b, а не к b. Если b является изменяемым, a wiil является ссылкой на b

Как уже упоминалось ранее, в Python нет таких ссылок , как ссылки . Имена в Python привязаны к объектам. Различные имена (или переменные) могут быть привязаны к одному и тому же объекту, но нет никакой связи между разными именами. Когда вы изменяете вещи, вы изменяете объекты , поэтому все другие имена, привязанные к этому объекту, «видят изменения», ну, они привязаны к тому же объекту, который вы изменили, не так ли?

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

Что касается примера со списками:

 In [1]: smalllist = [0, 1, 2] In [2]: biglist = [smalllist] In [3]: biglist Out[3]: [[0, 1, 2]] 

Вместо In [1] и In [2] я мог бы написать:

 In [1]: biglist = [[0, 1, 2]] In [2]: smalllist = biglist[0] 

Это эквивалентно.

Важная вещь, чтобы увидеть здесь, заключается в том, что biglist – это список с одним элементом. Этот предмет, конечно, является объектом. Тот факт, что это список, не вызывает какой-либо магии, это просто простой объект, который является списком, который мы привязали к smalllist .

Таким образом, доступ к biglist [i] в ​​точности совпадает с доступом к мелкому списку, потому что они являются одним и тем же объектом. Мы никогда не делали копию, мы передавали объект.

 In [14]: smalllist is biglist[0] Out[14]: True 

Поскольку списки изменяемы, мы можем изменить smallist и увидеть изменение, отраженное в biglist. Зачем? Потому что мы фактически модифицировали объект, на который ссылается малый. У нас все еще есть один и тот же объект (кроме того, что он изменился). Но biglist «увидит» это изменение, потому что в качестве первого элемента он ссылается на тот же самый объект.

 In [4]: smalllist[0] = 3 In [5]: biglist Out[5]: [[3, 1, 2]] 

То же самое верно, когда мы «удваиваем» список:

 In [11]: biglist *= 2 In [12]: biglist Out[12]: [[0, 1, 2], [0, 1, 2]] 

Что происходит: у нас есть список: [object1, object2, object3] (это общий пример). Мы получаем: [object1, object2, object3, object1, object2, object3]: он будет просто вставлять (т. Е. Изменять «biglist») все элементы в конце списка. Опять же, мы вставляем объекты, мы не волшебным образом создаем копии.

Поэтому, когда мы теперь меняем элемент внутри первого элемента biglist:

 In [20]: biglist[0][0]=3 In [21]: biglist Out[21]: [[3, 1, 2], [3, 1, 2]] 

Мы могли бы просто изменить smalllist , потому что для всех целей и целей biglist может быть представлен как: [smalllist, smalllist] – он содержит один и тот же объект дважды.

Python - лучший язык программирования в мире.