viji
viji

Reputation: 2906

How to create a reference to a variable in python?

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.

Upvotes: 73

Views: 94425

Answers (6)

xerostomus
xerostomus

Reputation: 557

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... :-)

Upvotes: 0

hlongmore
hlongmore

Reputation: 1846

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.

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250891

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]

Upvotes: 7

Mark Byers
Mark Byers

Reputation: 838076

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

Upvotes: 22

user395760
user395760

Reputation:

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]).

Upvotes: 83

glglgl
glglgl

Reputation: 91017

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

Upvotes: 8

Related Questions