Указатели в Python? ` x.pointerDest = y.pointerDest`?
Я разбиваю свой старый вопрос на части, потому что здесь очень грязный зверь. Этот вопрос связан с этим ответом и этим ответом. Я пытаюсь понять указатели, даже не уверен, существуют ли они в Python.
# Won't change x with y=4
>>> x = 0; y = x; y = 4; x
0
# Won't change y
>>> x = 0; y = x; x = 2; y
0
#so how can I change pointers? Do they even exist in Python?
x = 0
y.pointerDestination = x.pointerDestination #How? By which command?
x = 2
# y should be 0, how?
[Обновление 2: решено]
Возможно, противоречивые заявления о существовании There are no pointers in Python.
а также Python does not have the concept of a "pointer" to a simple scalar value.
, Выводит ли последний, что есть указатели на что-то еще, сводя на нет первое утверждение?
3 ответа
Скалярные объекты в Python неизменны. Если вы используете нескалярный объект, такой как список, вы можете сделать это:
>>> x = [0]
>>> y = x
>>> y[0] = 4
>>> y
[4]
>>> x
[4]
>>> x is y
True
В Python нет понятия "указатель" на простое скалярное значение.
Не путайте указатели на ссылки. Они не одно и то же. Указатель - это просто адрес объекта. На самом деле у вас нет доступа к адресу объекта в Python, только ссылки на них.
Когда вы назначаете объект переменной, вы назначаете ссылку на некоторый объект переменной.
x = 0
# x is a reference to an object `0`
y = [0]
# y is a reference to an object `[0]`
Некоторые объекты в Python являются изменяемыми, что означает, что вы можете изменить свойства объекта. Другие являются неизменяемыми, то есть вы не можете изменить свойства объекта.
int
(скалярный объект) неизменен. Там нет собственности int
что вы могли бы изменить (иначе мутировав).
# suppose ints had a `value` property which stores the value
x.value = 20 # does not work
list
(нескалярный объект), с другой стороны, является изменчивым. Вы можете изменить отдельные элементы списка, чтобы ссылаться на что-то еще.
y[0] = 20 # changes the 0th element of the list to `20`
В примерах, которые вы показали:
>>> x = [0]
>>> y = [x]
вы не имеете дело с указателями, вы имеете дело со ссылками на списки с определенными значениями. x
это список, который содержит одно целое число 0
, y
это список, который содержит ссылку на что-либо x
относится к (в данном случае, список [0]
).
Вы можете изменить содержимое x
вот так:
>>> print(x)
[0]
>>> x[0] = 2
>>> print(x)
[2]
Вы можете изменить содержимое списка, на который ссылается x
через y
Ссылка:
>>> print(x)
[2]
>>> print(y)
[[2]]
>>> y[0][0] = 5
>>> print(x)
[5]
>>> print(y)
[[5]]
Вы можете изменить содержимое y
сослаться на что-то еще:
>>> print(y)
[[5]]
>>> y[0] = 12345
>>> print(x)
[5]
>>> print(y)
[12345]
Это в основном та же семантика языка, как Java или C#. Вы не используете указатели на объекты напрямую (хотя вы используете косвенно, так как реализации используют указатели за кулисами), но ссылаются на объекты.
В Python нет указателей. Существуют вещи, называемые ссылками (которые, как и ссылки на C++, обычно реализуются в указателях, но в отличие от ссылок на C++ не подразумевают передачу по ссылке). Каждая переменная хранит ссылку на объект, размещенный где-то еще (в куче). Каждая коллекция хранит ссылки на объекты, размещенные где-то еще. Каждый член объекта хранит ссылку на объект, размещенный где-то еще.
Простое выражение x
оценивает ссылку, хранящуюся в x
- тот, кто его использует, не может определить, что получено из переменной. Нет способа получить ссылку на переменную (в отличие от ее содержимого), которую можно использовать для отслеживания изменений этой переменной. Вещь (x[y] = ...
) и член (x.y = ...
) назначения различны в одном отношении: они вызывают методы и изменяют существующие объекты вместо перезаписи локальной переменной. Это различие главным образом важно при работе со областью видимости, но вы можете использовать любой из них для эмуляции изменчивости для неизменяемых типов (как показано @Greg Hewgill) и для обмена изменениями состояния через границы функций (def f(x): x = 0
ничего не меняет, но def g(x): x.x = 0
делает). Это не полностью до эмуляции передачи по ссылке - если только вы не замените каждую переменную объектом-оберткой, единственной целью которого является хранение изменяемого val
имущество. Это было бы эквивалентно эмуляции передачи по ссылке через указатели в C, но гораздо более громоздко.