This question already has answers here:
python: mutating the copy of a list changes the original?
(1 answer)
Why should I refer to "names" and "binding" in Python instead of "variables" and "assignment"?
(5 answers)
Closed 3 years ago.
#Case 1
myList=[1,2,3,4]
old=myList
myList=[5,6,7,8]
print(old)
#Case 2
myList=[1,2,3,4]
old=myList
myList[0]=10
print(old)
#Case 3
myList=[1,2,3,4]
old=myList.copy()
myList[0]=10
print(old)
[1, 2, 3, 4]
[10, 2, 3, 4]
[1, 2, 3, 4]
For me the case 3 is the safe case and Case 2 is clear. However, I am not able to clearly understand why in case 1 old is not changed.
In case 1, we are re-assigning a brand new list to the name myList. The original list that was assigned to myList is not affected by this operation; myList is now simply pointing to a different object
This becomes clear when we look at the ids of the objects:
>>> myList = [1,2,3,4]
>>> print(id(myList))
47168728
>>> old = myList
>>> print(id(old))
47168728
>>> myList = [5,6,7,8]
>>> print(id(myList))
47221816
>>> print(id(old))
47168728
Writing old = myList does not bind the two variables inextricably; it assigns the value of myList to old at that point in time. By reassigning myList to a new list afterwards, you are then making myList and old point to different values.
Related
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 1 year ago.
I have a list of lists that contain a list at the end. If this list has more than one element, I want to duplicate the entry and for each with the individual value without being in the list.
E.g.
[[1, [1,2]] -> [[1, 1][1, 2]]
There's probably a much more efficient solution than the one I've tried, but I'd like to understand why you're giving me the mistakes you're giving.
First, even though it indicates that it is not the same list, it is changing the value in both lists. Second, when I create the second element, it changes the previous one as well. Any explanation is welcome. Thanks
Variables in Python are just references. I recommend making a copy by using a slice. l_copy = l_orig[:]
When I first saw the question (pre-edit), I didn't see any code, so I did not have the context. It looks like you're copying the reference to that row. (Meaning it actually points to the sub-lists in the original.)
new_list.append(row[:])
Weird right? Look at the following example
lst1 = [1,2,3]
#bad copy example
_
lst2 = lst1
-
lst2.append(4)
print(lst1,lst2)
You would expect that only lst2 should have 4, but no. lst1 and lst2 both have 4.
[1, 2, 3, 4] [1, 2, 3, 4]
So to avoid a problem like this, we can use list2 = list1.copy()
lst1 = [1,2,3]
lst2 = lst1.copy()
lst2.append(4)
print(lst1,lst2)
output
[1, 2, 3] [1, 2, 3, 4]
This question already has answers here:
what is the difference between a = x and a=x[:] in python [duplicate]
(3 answers)
What is the difference between list and list[:] in python?
(7 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 2 years ago.
nLst1 = ['A','B','C','D']
nLst2 = nLst1
# And
nLst3 = nLst1[:]
nLst2 = nLst1 makes nLst2 point to the same memory as nLst1, which means that modifying the contents of one array will modify the other:
list1 = [1, 2, 3]
list2 = list1
list2[0] = 3
list1 # [3, 2, 3]
However, nLst3 = nLst1[:] makes a copy of nLst1, so the 2 arrays are disjoint:
list1 = [1, 2, 3]
list2 = list1[:]
list2[0] = 3
list1 # still [1, 2, 3]
Read more here.
First one is not copy, it will point both lost to same memory address, and the second one will copy. If the first one is implemented, then changing one will affect another. The second will define a new slice copy of the list that will point to diferent memory address, you can do it using list.copy() too, and they will both take O(n)
This question already has answers here:
Passing values in Python [duplicate]
(8 answers)
Closed 2 years ago.
Consider the Python code below:
def change_list(in_list):
in_list = [1,2,3]
def change_list_append(in_list):
in_list.append(7)
my_list = [1,2,3,4,5,6]
change_list(my_list)
print(my_list)
change_list_append(my_list)
print(my_list)
The output is:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
I don't understand why the first call (change_list) did not result in my_list to become [1,2,3]. Can someone explain? Look at what happens with the call to change_list_append: number 7 is appended to my_list.
Assigning to a name never changes the value previously referenced by the list. This is true even without invoking function parameters.
>>> x = [1,2,3]
>>> y = x
>>> y = [4,5,6]
>>> x
[1, 2, 3]
Changing what y refers to does not alter what x refers to.
In your second example, you are invoking a mutating method on the list referenced by the parameter. Both my_list and in_list refer to the same list, so it any changes made to the list via either reference are visible from either reference.
See https://nedbatchelder.com/text/names.html for a more in-depth discussion of how references work in Python.
I think this post sums it up nicely => Why can a function modify some arguments as perceived by the caller, but not others?
You can assign items to the in_list using methods (like the .clear() method or the .assign() ) not rename.
As mentioned by others, the 1st function does not modify the global my_list. Instead it modifies the local variable
If you want change_list to modify the global variable you need to the function to return the new value and assign it to my_list.
Something like this will do:
def change_list():
newList = [1,2,3]
return newList
def change_list_append(in_list):
in_list.append(7)
my_list = [1,2,3,4,5,6]
my_list = change_list()
print(my_list)
change_list_append(my_list)
print(my_list)
Output:
[1, 2, 3]
[1, 2, 3, 7]
This question already has answers here:
List comprehension vs. lambda + filter
(17 answers)
How to remove an element from a list by index
(18 answers)
Closed 6 years ago.
I saw there are several topics on removing items from a list, including using remove(), pop(), and del. But none of these is what I am looking for, since I want to get a new list when the items are removed. For example, I want to do this:
a = [1, 2, 3, 4, 5, 6]
<fill in > # This step somehow removes the third item and get a new list b and let
b = [1, 2, 4, 5, 6]
How can I do this?
If you want to have a new list without the third element then:
b = a[:2] + a[3:]
If you want a list without value '3':
b = [n for n in a if n != 3]
This question already has answers here:
Are lists mutable? [duplicate]
(6 answers)
Closed 7 months ago.
When I type following code,
x=[1,2,4]
print(x)
print("x",id(x))
x=[2,5,3]
print(x)
print("x",id(x))
it gives the output as
[1, 2, 4]
x 47606160
[2, 5, 3]
x 47578768
If lists are mutable then why it give 2 memory address when changing the list x?
You created a new list object and bound it to the same name, x. You never mutated the existing list object bound to x at the start.
Names in Python are just references. Assignment is binding a name to an object. When you assign to x again, you are pointing that reference to a different object. In your code, you simply created a whole new list object, then rebound x to that new object.
If you want to mutate a list, call methods on that object:
x.append(2)
x.extend([2, 3, 5])
or assign to indices or slices of the list:
x[2] = 42
x[:3] = [5, 6, 7]
Demo:
>>> x = [1, 2, 3]
>>> id(x)
4301563088
>>> x
[1, 2, 3]
>>> x[:2] = [42, 81]
>>> x
[42, 81, 3]
>>> id(x)
4301563088
We changed the list object (mutated it), but the id() of that list object did not change. It is still the same list object.
Perhaps this excellent presentation by Ned Batchelder on Python names and binding can help: Facts and myths about Python names and values.
You did not mutate (change) the list object referenced by x with this line:
x=[2,5,3]
Instead, that line creates a new list object and then reassigns the variable x to it. So, x now references the new object and id(x) gives a different number than before:
>>> x=[1,2,4] # x references the list object [1,2,4]
>>> x
[1, 2, 4]
>>> x=[2,5,3] # x now references an entirely new list object [2,5,3]
>>> x
[2, 5, 3]
>>>
You are not mutating the list, you are creating a new list and assigning it to the name x. That's why id is giving you different outputs. Your first list is gone and will be garbage-collected (unless there's another reference to it somewhere).