74

In the code:

y = 7
x = y
x = 8

y will be 7 and x will be 8. But I actually want changing x to change y at the same time. Can I assign the reference of y and do that?

For example, in C++ the same thing can be achieved with:

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

Now, both y and x will be 9.

6 Answers 6

84

No, you cannot. As other answer point out, you can (ab?)use aliasing of mutable objects to achieve a similar effect. However, that's not the same thing as C++ references, and I want to explain what actually happens to avoid any misconceptions.

You see, in C++ (and other languages), a variable (and object fields, and entries in collections, etc.) is a storage location and you write a value (for instance, an integer, an object, or a pointer) to that location. In this model, references are an alias for a storage location (of any kind) - when you assign to a non-reference variable, you copy a value (even if it's just a pointer, it's still a value) to the storage location; when you assign to a reference, you copy to a storage location somewhere else. Note that you cannot change a reference itself - once it is bound (and it has to as soon as you create one) all assignments to it alter not the reference but whatever is referred to.

In Python (and other languages), a variable (and object fields, and entries in collections, etc.) is a just a name. Values are somewhere else (e.g. sprinkled all over the heap), and a variable refers (not in the sense of C++ references, more like a pointer minus the pointer arithmetic) to a value. Multiple names can refer to the same value (which is generally a good thing). Python (and other languages) calls whatever is needed to refer to a value a reference, despite being pretty unrelated to things like C++ references and pass-by-reference. Assigning to a variable (or object field, or ...) simply makes it refer to another value. The whole model of storage locations does not apply to Python, the programmer never handles storage locations for values. All he stores and shuffles around are Python references, and those are not values in Python, so they cannot be target of other Python references.

All of this is independent of mutability of the value - it's the same for ints and lists, for instance. You cannot take a variable that refers to either, and overwrite the object it points to. You can only tell the object to modify parts of itself - say, change some reference it contains.

Is this a more restrictive model? Perhaps, but it's powerful enough most of the time. And when it isn't you can work around it, either with a custom class like the one given below, or (equivalent, but less obvious) a single-element collection.

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

That still won't allow you to alias a "regular" variable or object field, but you can have multiple variables referring to the same Reference object (ditto for the mutable-singleton-collection alternative). You just have to be careful to always use .get()/.set() (or [0]).

Sign up to request clarification or add additional context in comments.

5 Comments

Good explanation, +1 for clarifying that it has nothing to do with mutability.
Can anyone explain the meaning of (ab?) in this answer?
@Daniel Roseman Can you explain the meaning of (ab?) in this answer?
This is a great answer and I think it's a good candidate to become a community answer. Adding example of languages for each paradigm could be very useful as well.
@FadyHany I think that you can read the part "you can (ab?)use aliasing" either as "you can use aliasing" or as "you can abuse aliasing", indicating that this workaround may be considered to be hacky by some developers.
22

No, Python doesn't have this feature.

If you had a list (or any other mutable object) you could do what you want by mutating the object that both x and y are bound to:

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

See it working online: ideone

1 Comment

Although this is really helpful there is more or less big downside in this "mutation" of a single simple numerical value. Turning the integer in a list with a single element requires little more than 3 times the memory space you'll normally need. Example (I'll use sys.getsizeof(...) to illustrate the size-difference): x = 1 -> sys.getsizeof(x) -> give us 14 -> x = [1] -> sys.getsizeof(x) -> gives us 36
8

Alternatively, you could use a self crafted container.

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

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

ideone

Comments

6

You should use a mutable object for this.

In python x & y are just references to objects so y = 7 means y points to the object 7. x=y means x too points to 7, but as 7 is immutable so changing the value of x simply changes the object 7 and y still remains pointing to 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]

1 Comment

you wanted to point out that y remains unchanged even after changing x, but that is not what you wrote here. Please clarify.
1

While it is not the same thing as a reference in C++, depending on the use case one might find the weakref module in the Python standard library of use.

A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.

A primary use for weak references is to implement caches or mappings holding large objects, where it’s desired that a large object not be kept alive solely because it appears in a cache or mapping.

Comments

0

I wonder whether the functions eval() and exec() would satisfy your needs.

y = 7
x = "y"
eval(x) # 7
y = 8
eval(x) # 8
exec(x+"=9")
y # 9
eval(x) # 9

But I agree that if you get used to pointers in C, it is hard to live without them. The same with women in life. So if we loose them in life or in Python we do our best to get them back... :-)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.