Присвоение и изменение переменных в отношении адресов памяти - PullRequest
2 голосов
/ 13 мая 2019

Предположим, я назначил две переменные целым числам:

a = 1
b = 2

Теперь я назначу a b:

a = b

Как и ожидалось, a == 2,потому что a был установлен на адрес памяти b.

Но на самом деле это не так.Если я сделаю

b += 1

a все равно равно 2.Почему a не указывает на b?

Ответы [ 3 ]

3 голосов
/ 13 мая 2019

Поведение в этом примере выглядит следующим образом

In [1]: a = 1                                                                                                                                                                     

In [2]: b = 2                                                                                                                                                                     

In [3]: a = b                                                                                                                                                                     

In [4]: b+=1                                                                                                                                                                      

In [5]: b                                                                                                                                                                         
Out[5]: 3

In [6]: a                                                                                                                                                                         
Out[6]: 2

В этом примере, когда вы делаете a=b, и a, и b указывают на одну и ту же ссылку, но когда вы b += 1,операция добавления 1 к b, создает новое целочисленное значение 3 для b и b указывает на это значение, но a все еще указывает на старое значение 2

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

In [1]: a = [1]                                                                                                                                                                   

In [2]: b = [2]                                                                                                                                                                   

In [3]: a = b                                                                                                                                                                     

In [4]: b.append(2)                                                                                                                                                               

In [5]: a                                                                                                                                                                         
Out[5]: [2, 2]

In [6]: b                                                                                                                                                                         
Out[6]: [2, 2]

In [7]: b += [3, 4];                                                                                                                                                                        

In [8]: b
Out[8]: [2, 2, 3, 4]

In [9]: a
Out[9]: [2, 2, 3, 4]

Что теперь здесь произошло?Мы изменили b, но a также изменилось, это потому, что append или обновление списка происходит in-place, и поскольку a указывает на b, оба заканчивают тем, что обновляются!

То, что происходит для оператора +=, определяется методом __iadd__ класса.Для int -s все методы __iXXX__ возвращают новый экземпляр типа int.Для list -s __iadd__(self, other) делает self.extend(other); return self, поэтому переменная продолжает указывать на один и тот же объект.

В результате даже целые числа могут вести себя как список, например здесь вежливость @ imposeren

0 голосов
/ 13 мая 2019

В других языках программирования то, о чем вы говорите, называется «указатели».
У них есть это имя, потому что они «указывают» на вещи.
a указывает на b, b указывает на 2 и т. Д.

Я нарисовал несколько картинок, чтобы описать, что, по вашему мнению, произойдет, и что на самом деле произошло.

То, что вы ожидали, случится:

enter image description here

Что на самом деле произошло:

picture of actual behavior

0 голосов
/ 13 мая 2019

Переменные в python являются ссылками. Немногие ссылки на неизменяемые объекты (такие как строки, целые числа и т. Д.), Тогда как списки и наборы являются изменяемыми.

Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 22:20:52) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
# Consider two variables x & y  with integers 23 and 46. They have immutable references
# Meaning, if y=x, it doesn't mean y will change whenever x is updated.
>>> x=23
>>> print (x)
23
>>> y=46
>>> print (x)
23
>>> print (y)
46
>>> y=x
>>> print (x)
23
>>> print (y)
23
# Let's change the value of x after the assignment
>>> x=99
>>> print (x)
99
# Since it is immutable, the value wont change.
>>> print (y)
23
#Let's consider the mutable reference scenario. a & b are two lists which have mutable references
# Meaning, if b=a, it means b will change whenever a is changed
>>> a = list([11,22,33,87])
>>> print (a)
[11, 22, 33, 87]
>>> b = list([87,53,98,2])
>>> print (b)
[87, 53, 98, 2]
>>> a=b
>>> print (a)
[87, 53, 98, 2]
>>> print (b)
[87, 53, 98, 2]
# Popping the list would alter b
>>> b.pop()
2
>>> print (b)
[87, 53, 98]
# Notice the change in value of a
>>> print (a)
[87, 53, 98]
>>>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...