0

I come from R and am trying to get a better grip on mutability. Below is code, the first two parts of which I think I understand (see comments). I do not understand the third part.

#1. Refering to same instance with two variable names
listOrig = [i for i in range(1001, 1011)]
listCopy = listOrig
listOrig[0]=999
listOrig == listCopy #Returns True, because both variable names actually refer
#to the same instance, ergo still containing the same values
listOrig[0] is listCopy[0] #Same instance 999, the id is also the same as a 
#consequence

#2. Refering to same part of original list through slicing
listSlice = listOrig[0:5] 
listOrig[0] is listSlice[0] #Returns True, analogous to above
a = 999
listOrig[0] == a #True because it's the same value or number
listOrig[0] is a #False because they are different instances with different IDs
  
#3. WHAT I DO NOT UNDERSTAND: changing the sliced copy does not affect the original list
listOrig
listSlice
listSlice[0] = 1001
listOrig[0] is listSlice[0] #Different number, thus also obviously different ID
Spaniel
  • 329
  • 3
  • 15
  • 1
    The slice is a copy of a particular range from the original list. Altering the copy does not alter the original. Because it is a copy. – khelwood Dec 01 '21 at 14:19
  • But listOrig[0] is listSlice[0] is True, should it not be False if what you say is correct? – Spaniel Dec 01 '21 at 14:20
  • 1
    All that shows is that the copy contains some of the same objects that are in the original. Then after you do `listSlice[0] = 1001` it contains something else instead. – khelwood Dec 01 '21 at 14:21
  • Then I do not understand your answer. What is the relationship between the ids of the lists and the items within? I think my problem lies there. The lists have distinct names, but share the same objects (and thus IDs). Creating a copy without slicing creates a new reference to the same instance. Slicing seems to do the same. But when I change a value of the sliced object, it does not affect the original list, but all other instances are identical in terms of id. Why is that? What is the mechanic behind that? Thanks your help! – Spaniel Dec 01 '21 at 14:24
  • 2
    The slice is a new list containing some of the same objects. Those same objects will still have the same id. When you reassign a position in the new list, you're putting a different object in that list, but not in the original list. Because it is a different list. – khelwood Dec 01 '21 at 14:26
  • I can see what you are saying, as is demonstrated by the code, but my expectation would be that making changes to the sliced list (listSlice) has the same effect on the original list as making changes to an unsliced "copy" reference (listCopy ) to the original list (listOrig). – Spaniel Dec 01 '21 at 14:28
  • Does this answer your question? [List changes unexpectedly after assignment. Why is this and how can I prevent it?](https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it) – Vorsprung Dec 01 '21 at 14:29
  • Your `listCopy` is not a copy at all. It is the same list assigned to a new variable. – khelwood Dec 01 '21 at 14:29
  • @Vorsprung Not really : / It says "so both new_list and my_list refer to the same list after the assignment." I understand that, but from what I see above, a sliced list behaves differently that an "unsliced" new reference to the same list instance when changes are made to it. – Spaniel Dec 01 '21 at 14:32
  • @khelwood Sorry, do not want to be pedantic. I just don't get it. You are right. listCopy refers to the same instance as listOrig. You also said slicing creates a new list. So does that mean that when I slice, a new list is created, but the objects it contains are actually still the same instances as in listOrig? But then what is the difference? The lists themselves are not referring to the same list instance, but the instances within the different lists are still identical? – Spaniel Dec 01 '21 at 14:35
  • 3
    The slice is a new list that contains objects from the original list. Not copies of the objects, the same objects. The list is a new list. The contents are new references to existing objects, not copies. – khelwood Dec 01 '21 at 14:38
  • Okay, thank you @khelwood! I guess that answers my question! Thanks a lot! – Spaniel Dec 01 '21 at 14:43

2 Answers2

5

I am going to post an answer just because I think this is better explained with diagrams.

Suppose you create a list list_1 containing the numbers 1, 2 and 3.

list_1 = [1,2,3]

list_1

Then you assign the list to a new variable.

list_2 = list_1

It is another reference to the same original list.

list_2

Alternatively, suppose you take a slice of your list.

list_3 = list_1[:]

It is a new list with references to the same objects.

list_3

So if you reassign an element in the new list, it does not affect the original.

list_3[0] = 4

changed list_3

khelwood
  • 55,782
  • 14
  • 81
  • 108
0

As is said in the comments, the slice is a copy of the original list. It currently (when the values are same) refers to same memory address and hence the id (with e.g. id-function) is the same and listOrig[0] is listCopy[0] is True.

Below example formulates this: even if you set two different integer variables b and c to be the same value, their ids are same. However, if you change the value of b, the value of c does not change. You can also check print(id(listSlice), id(listOrig[0:5])) from your example which shows, that the ids of the slice-variable and the original slice are different

a = 1
b = 2
c = 2

print(id(a))
print(id(b))
print(id(c))

print(b is c)

The output would be e.g.

2770111129904

2770111129936

2770111129936

True
tiitinha
  • 54
  • 1
  • 3
  • 1
    This only holds true for numbers smaller than more or less 600 – Spaniel Dec 01 '21 at 14:41
  • strings work like that in Java – Vorsprung Dec 01 '21 at 14:43
  • 1
    See: https://stackoverflow.com/questions/15171695/whats-with-the-integer-cache-maintained-by-the-interpreter – Spaniel Dec 01 '21 at 14:46
  • @Spaniel well probably it would "work" for larger int literals as well. But this is just *confusing*, because this is an implementation detail about how the compiler handles immutable literals in the same block of code, it doesn't address the OP's question – juanpa.arrivillaga Dec 01 '21 at 15:49
  • "Below example formulates this: even if you set two different integer variables b and c to be the same value, their ids are same" this is **wrong** – juanpa.arrivillaga Dec 01 '21 at 15:50