1

I'm trying to accomplish something with Python but I can't find info about this at all on internet so here is my problem.

Having this sample code:

a = 5
b = [a]

I need b[0] to be a pointer reference to a. Currently if I do

b[0] = 7

a.var will still be 5, and if I set value to a b[0], a keeps the same.

I'd like to know if there is any way in Python to store an Object in an array without copying this, so if I modify one I also modify another.

EDIT ONE

I want to clarify a bit better what I'm trying to accomplish so maybe I can find the real answer.

I have a custom class like

class Foo(object):
    def __init__(self):
        self.var = 7

I have also a list like this:

myList = [Foo()]

My real problem is here:

In some place of a code, I need to do the following assignment:

self.foo = myList[0]

Then when I try to access this foo var, I notice this is never updated from the original instance. So basically that is what I need.

Edit Two

All answers were right. Using id(var) on every step of my assignments I could verify the Object was the same all the time, so the error must be somewhere else. Thanks to everyone for all the help and I hope this post can help someone else in a future.

Aitor Martin
  • 724
  • 1
  • 11
  • 26
  • Sorry, integers are immutable. When `a` refers to an int, the only way to modify it is to do `a = some_other_value`. – Kevin Sep 23 '14 at 19:22
  • 1
    In Python, assignment never copies objects; variables are all references, and assignment rebinds references. See the [Python execution model](https://docs.python.org/2/reference/executionmodel.html) and [Semantics of Python variable names from a C++ perspective](http://rg03.wordpress.com/2007/04/21/semantics-of-python-variable-names-from-a-c-perspective/). – user2357112 Sep 23 '14 at 19:23
  • This was just an example, I actualy need an OBJECT not an integer – Aitor Martin Sep 23 '14 at 19:23
  • Even after the edit, that should still work fine. See my answer for some demonstration code. – Roger Fan Sep 23 '14 at 19:36
  • Please review my answer and tell me if it helps. – Russia Must Remove Putin Sep 23 '14 at 19:36
  • What do you mean by "this is never updated from the original instance"? Can you give an example of what you actually try to then do with `self.foo` and/or `myList`, and what it does that surprises you? – BrenBarn Sep 23 '14 at 19:38

3 Answers3

5

You already are storing the object, namely the integer 5. What you are not storing is the name-value binding between the name a and the value 5. Your problem is that the operation b[0] = 7 does not modify the object 5; it only modifies the binding between b[0] and its value (from 5 to 7), leaving the values themselves (5 and 7) untouched. In fact, you cannot modify the value 5, since 5 is an integer, and integers in Python are immutable.

Another way to say that is that b[0] = 7 does not modify the object referred to by b[0]; instead, it modifies the object referred to by b. b is a list, and lists are objects that internally keep track of what objects their indices point to. When you do b[0] = 7, this tells b "make your 0 index point at this new object". It does not "notify" 5 (the old value) or 7 (the new value) that they are now pointed to by b[0]. Objects in Python do not know what kinds of references point at them; they only know what they point at (if anything).

What you are asking for is not a way to store an object, but to store a "variable" --- that is, a binding between a name in the local namespace and a value. The answer is that there isn't, in general, a way to do this in Python. There's no construct that will allow you do b = something(a) so that when you later do b[0] = 8, a will change.

If you want to be able to modify the name-value binding, you need to change a, by making it some kind of object whose contents can be changed, instead of just making it a plain variable. For instance, if you do:

a = [5]
b = a
b[0] = 7

Then you will find a has also changed. The same will be true for other kinds of objects as well: if you set a to some other kind of object whose properties can be altered, and then you alter its properties in-place, those changes will show up no matter how you reference the object.

You may find it helpful to read up on how Python variables work, for instance in this article and this one.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
3

Whether you can do this comes down to whether your list elements are immutable or mutable types. Immutable types can't be changed, so when you re-assign a variable that is immutable it's actually creating a new object and labeling it with the same label. Mutable types can be changed, so it's possible to change the underlying object without reassigning it.

For example, say that a is a list, which is a mutable type.

a = [5]
b = [a]
a[0] = 3
print(b)
# [[3]]

a.append('hi')
print(b)
# [[3, 'hi']]

Your test code actually works the way you want it, because objects are mutable.

class Object():
    pass

a = Object()
a.var = 5

b = [a]
b[0].var = 7

print(a.var)
# 7

Your other example code should still work, for all the same reasons. When I assign a = l[0], it isn't copying anything, it's just creating an additional reference a to the object that l[0] references.

l = [Object() for _ in range(5)]
l[0].var = 5

a = l[0]
l[0].var = 7

print(a.var)
# 7
Community
  • 1
  • 1
Roger Fan
  • 4,945
  • 31
  • 38
  • Printing IDs I saw the object is exactly the same, so I see that the error behind not being updated should be somewhere else. I'll mark your answer as correct because is the most close one to answer my question if it was really the problem. Thanks for the help – Aitor Martin Sep 23 '14 at 19:40
1

You write

a = 5

b = [a]

I need b[0] to be a pointer reference to a.

You can't. You can make a point to a mutable object and change the value for that object:

class Object(object): 
    '''an object'''

a = Object()
a.value = 5
b = a
b.value = 7

and now a.value returns:

7

Similarly, but with a list this time:

a = [5]
b = a
b[0] = 7

and now a[0] is:

7
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331