Назначение ссылки на переменную Python

В коде

y = 7
x = y    
x = 8

Теперь y будет 7, а x будет 8. Но на самом деле я хочу изменить y. Можно ли присвоить ссылку y и сделать это?

Например, на С++ то же самое можно достичь, например,

int y = 8;
int &x = y;
x = 9;

Теперь и y, и x будут 9

Ответ 1

Нет, вы не можете. Как следует из другого ответа, вы можете (ab?) Использовать сглаживание изменчивых объектов для достижения аналогичного эффекта. Однако это не то же самое, что и ссылки на С++, и я хочу объяснить, что на самом деле происходит, чтобы избежать каких-либо заблуждений.

Вы видите, что в С++ (и других языках) переменная (и поля объекта, и записи в коллекциях и т.д.) является местом хранения, и вы пишете значение (например, целое число, объект или указатель) в это место. В этой модели ссылки являются псевдонимом для места хранения (любого вида) - при назначении переменной без ссылки вы копируете значение (даже если это только указатель, это все еще значение) в место хранения; когда вы назначаете ссылку, вы копируете в место хранения где-то в другом месте. Обратите внимание: вы не можете сами изменить ссылку - как только она привязана (и она должна быть как только вы ее создадите), все присваивания к ней изменяют не ссылку, а все, что упоминается.

В Python (и других языках) переменная (и поля объекта, и записи в коллекциях и т.д.) - это просто имя. Значения находятся где-то в другом месте (например, посыпаны всей кучей), а переменная ссылается (не в смысле ссылок на С++, больше как указатель минус арифметика указателя) на значение. Несколько имен могут ссылаться на одно и то же значение (что обычно хорошо). Python (и другие языки) вызывает все, что необходимо, чтобы ссылаться на значение ссылки, несмотря на то, что оно довольно не связано с такими вещами, как ссылки на С++ и pass-by-reference. Присвоение переменной (или полем объекта или...) просто означает, что она ссылается на другое значение. Вся модель расположения хранилищ не относится к Python, программист никогда не обрабатывает места хранения для значений. Все, что он хранит и перемешивает, это ссылки на Python, и они не являются значениями в Python, поэтому они не могут быть объектом других ссылок на Python.

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

Является ли это более ограничительной моделью? Возможно, но это достаточно эффективно в большинстве случаев. И когда это не так, вы можете обойти это, либо с помощью специального класса, как тот, который приведен ниже, или (эквивалентный, но менее очевидный) одноэлементный набор.

class Reference:
    def __init__(self, val):
        self._value = val # just refers to val, no copy

    def get(self):
        return self._value

    def set(self, val):
        self._value = val

Это все равно не позволит вам использовать псевдоним "регулярной" переменной или поля объекта, но вы можете иметь несколько переменных, относящихся к одному и тому же объекту Reference (например, для альтернативы mutable-singleton-collection). Вам просто нужно быть осторожным, чтобы всегда использовать .get()/.set() (или [0]).

Ответ 2

Нет, Python не имеет этой функции.

Если у вас есть список (или любой другой изменяемый объект), вы можете сделать то, что хотите, путем изменения объекта, к которому привязаны как x, так и y:

>>> x = [7]
>>> y = x
>>> y[0] = 8
>>> print x
[8]

Посмотрите, как он работает в Интернете: ideone

Ответ 3

Для этого вы должны использовать изменяемый объект.

В python x и y есть только ссылки на объекты поэтому y = 7 означает, что y указывает на объект 7. x=y означает, что x тоже указывает на 7, но поскольку 7 неизменен, поэтому изменение значения x просто меняет объект 7 и y по-прежнему указывает на 7.

>>> y = [7]
>>> x = y
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7]
>>> y
[8]

Ответ 4

В качестве альтернативы вы можете использовать самодельный контейнер.

class Value(object):
    def __init__(self, value): self.value = value

y = Value(7)
x = y
x.value = 8
print y.value

ideone