0

After thinking a while this concept came to my mind which I was gone through few days ago.

In Python if I did x=y then automatically x and y will point same object reference location but is there any way I can manage to change y reference location but with same value if x.

for example:

x=100
y=x

now x and y share same object reference location of value 100 but I want to have a different location for y.

Edit: What I am trying to do

l1=[1,2,3,4]
l2=l1
i=0
j=len(l1)-1

while j >= 0 :
    l1[i]=l2[j]
    i=i+1
    j=j-1

    print("L1=",l1,"L2",l2,"i=",i,"j=",j)

What I am getting as outout

L1= [4, 2, 3, 4] L2 [4, 2, 3, 4] i= 1 j= 2
L1= [4, 3, 3, 4] L2 [4, 3, 3, 4] i= 2 j= 1
L1= [4, 3, 3, 4] L2 [4, 3, 3, 4] i= 3 j= 0
L1= [4, 3, 3, 4] L2 [4, 3, 3, 4] i= 4 j= -1

Thank you.

Raja G
  • 5,973
  • 14
  • 49
  • 82
  • 1
    You can't reliably achieve that. The value might e.g. be interned, with the system trying to avoid creating more than one instance. What are you trying to achieve with that? – Ulrich Eckhardt Mar 27 '16 at 06:25
  • @UlrichEckhardt I am trying to achieve list swapping with iteration and I am failing then. – Raja G Mar 27 '16 at 06:27
  • Still unclear. Give an example. In other words: You surely don't need this, there must be something else you're doing wrong. – Ulrich Eckhardt Mar 27 '16 at 06:28
  • @Selcuk my intention different. But thank you. – Raja G Mar 27 '16 at 06:32
  • @Raja The answer linked shows that you cannot have a different memory location for integers between -5 and 256 as they are cached. Your problem is not about the integer cache. When you write `l2=l1` you are copying the reference only. Use `l2=l1[:]` or `copy.copy(l1)`. – Selcuk Mar 27 '16 at 06:34
  • @Selcuk Thats I just came to know. Thank you. – Raja G Mar 27 '16 at 06:36
  • @Raja, or `l2 = list(l1)` – Rudziankoŭ Mar 27 '16 at 06:37

3 Answers3

2

This is unlikely to occur with small numbers because numbers are immutable in Python and the runtime is almost assuredly going to make x and y "point to" the same object in the object store:

>>> x = 100
>>> id(x)
4534457488
>>> y = 100
>>> id(y)
4534457488

Note that even by making y reference a new copy of 100, I still got the same object.

We can try:

>>> y = 25 * (5 - 1)
>>> id(y)
4534457488

Same.

If we used something mutable like lists, we could do:

>>> x = [1, 2, 3]
>>> id(x)
4539581000
>>> y = [1, 2] + [3]
>>> id(y)
4539578440
>>> x == y
True
>>> id(x) == id(y)
False

And now you have two variables, each referencing a different object in the object store, but the object values are equal.

As wRAR points, out, copy.copy can do things much more cleanly:

>>> from copy import copy
>>> x = [1, 2, 3]
>>> id(x)
4539578440
>>> y = copy(x)
>>> id(y)
4539580232

Tada. This is more inline with what you want, but notice it might not work for immutables like numbers!

>>> from copy import copy 
>>> x = 100
>>> id(x)
4534457488
>>> y = copy(x)
>>> y
100
>>> id(y)
4534457488

My Python interpreter is just going to make one int object with value 100 in the object store.

For larger numbers, this may not be the case. I tried:

>>> x = 393
>>> id(x)
4537495408
>>> y = 393
>>> id(y)
4539235760

I found information in this S.O. question where an answerer experimented with integers on the object pool. The number of pre-cached integer objects is probably implementation dependent in Python, whereas the JVM does define caching behavior.

Community
  • 1
  • 1
Ray Toal
  • 86,166
  • 18
  • 182
  • 232
  • Excellent , but so everytime I need to slice and append y[-1] so I can point to different object location. – Raja G Mar 27 '16 at 06:24
  • Well appending is a mutating operation which will not change the `id` of the list. You will want to copy or use `+` to make a new list. – Ray Toal Mar 27 '16 at 06:27
2

You can not do it with int. More over:

x = 100 
y = 100
x is y
>>> True

This is like a pool of small integers. They have only single representation in the memory.

With mutable objects you may do copy() operation:

a = [1]
b = copy(a)
a is b 
>>> False 
Rudziankoŭ
  • 10,681
  • 20
  • 92
  • 192
1

You can use copy.copy() for this.

wRAR
  • 25,009
  • 4
  • 84
  • 97
  • I tried this but it did not do what the OP wants: >>> from copy import copy `>>> x = 100 >>> id(x) 4534457488 >>> y = copy(x) >>> y 100 >>> id(y) 4534457488` – Ray Toal Mar 27 '16 at 06:21
  • would you mind giving an example ? : EDIT : Ray mentioned in his answer. Its good. Thanks for pointing out wRAR. – Raja G Mar 27 '16 at 06:24
  • @Ray Toal, see my answer, pleae. We cannot copy "small" `int` it has single representation – Rudziankoŭ Mar 27 '16 at 06:26
  • Right. [More info here](http://davejingtian.org/2014/12/11/python-internals-integer-object-pool-pyintobject/). – Ray Toal Mar 27 '16 at 06:36