This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 6 years ago.
Why does the code below output {'a': [1, 3, 4, 5, 6, 7, 8, 9], 'b': [1, 3, 4, 5, 6, 7, 8, 9]}
adic = {}
main_array = [1,2,3,4,5,6,7,8,9]
adic["a"] = main_array
adic["b"] = main_array
array = adic["a"]
array.remove(2)
print(adic)
I am not even assigning the new array to a key. Why should 2 be automatically removed from all the arrays in the dictionary. Am i missing something vital?
All your references point to the same list, as you can check by adding:
print(id(adic["a"]))
print(id(adic["b"]))
print(id(array))
print(id(main_array))
On my system:
32707888
32707888
32707888
32707888
Assignment does not create a copy.
There are several ways to copy a list if this is what you want, such as
new_list = list(old_list)
discussed here.
The reason why your output is doing that is because of the lines where you set each adic['value'] = main_array each of those statements is pointing to the same memory address of your main_array so when you do array = adic["a"] that's also pointing to the same memory address and when you remove 2 it's removing 2 from main_array. Because you are removing from main_array, everything that pointed to main_array is also affected.
Related
This question already has answers here:
What is the difference between shallow copy, deepcopy and normal assignment operation?
(12 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 1 year ago.
x=[3,6,9,[12]]
y=list(x)
x[3][0]=50
x[1]=25
print(y)
The output of the code is [3, 6, 9, [50]]
Why did 12 change to 50, but 6 didn't change to 25?
When you do list(x), python makes a copy of the list x and stores it in y. So if it was a list with all elements as integers for example -:
x = [1, 2, 3, 4]
y = list(x)
x[0] = 7
print(x, y)
[7, 2, 3, 4] [1, 2, 3, 4]
You will notice no change in the 0th index of y, that is because the integers are stored and copied with the list.
Python generally stores values at different memory addresses and variables are like pointers that point to that address so the value can be fetched as and when needed.[Thanks for pointing this out in the comments of the question #ShobitTewari]
So a list for example is a reference to the list stored in memory [1, 2, 3, 4].
But if the list has a nested list in it like so -: [1, 2, [12]]
then this inner list [12] is also having its value at some other memory address and the index just points to that address. Unlike integers nested lists aren't stored at the same address as the rest of the list.
So when you do list(x), python copies the whole list into a new memory address more on that here. But if you have a nested list, then the memory address of that lists still stays the same.
So when you change the value of that nested list's 0th index, it changes it in the memory and the pointer of y still points to that old memory address, so value of the nested list changes.
x = [1, 2, 3, [4]]
y = list(x)
x[3][0] = 7
print(x, y)
[1, 2, 3, [7]] [1, 2, 3, [7]]
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 does "list comprehension" and similar mean? How does it work and how can I use it?
(5 answers)
Closed 2 years ago.
I'm sure this question was asked time ago, but I can't find it because I don't know how to search for it.
Lately I'm seeing this kind of for everywhere. So I was wondering how does it work, what's it using for, and these stuff. I would be grateful if you could put multiple examples, equivalences in relation to other codes, etc. Thanks a lot.
This is the kind of for I'm asking for.
x = [x for x in range(len(ys))]
or
n = [ [ls[i] for i in t] for t in indexes(len(ls),k) ]
Thanks!
This is a list comprehension.
List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.
The basic structure you'll see often is [EXP for VAR in LIST] which iterates LIST, and for each element in the list, EXP is evaluated with VAR set to the respective list element.
Let's start with a list x that contains the integers 0 to 9:
>>> x = range(10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
You can use a list comprehension in a similar manner to map() to alter each element:
>>> [i * 2 for i in x]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
You can use it to filter out elements:
>>> [i for i in x if i % 2 == 0]
[0, 2, 4, 6, 8]
You can do both at the same time:
>>> [i * 2 for i in x if i % 2 == 0]
[0, 4, 8, 12, 16]
You don't even have to reference the iteration variable:
>>> ["foo" for i in x if i % 2 == 0]
['foo', 'foo', 'foo', 'foo', 'foo']
The second example in your question is an example of how to project a list for each element; in this particular case, the outer list being traversed contains iterables. This expression maps the inner iterables to lists. This can be used to map nested lists.
This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 3 years ago.
In python 3.7.4 I wnat to sort the array but I can't. I used the function sort and wrote this code -
arr = [0,5,8,9,6,3,1,2]
print(arr.sort())
output
None
Please help me.
Python's list.sort() modifies the list in-place and does not return it. For example:
x = [0,5,8,9,6,3,1,2]
print(x) # [0, 5, 8, 9, 6, 3, 1, 2]
x.sort()
print(x) # [0, 1, 2, 3, 5, 6, 8, 9]
See the docs for more information on list methods.
This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 4 years ago.
The given code flattens the vector but I'd like to understand the execution order of the two for loops. I've checked the Python Docs too but the execution pattern is not given.
>>> # flatten a list using a list comprehension with two 'for'
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [num for elem in vec for num in elem]
[1,2,3,4,5,6,7,8,9]
As I understand, execution order is like abstraction (left to right)? Is there any other opinion about it.
This link is flatten using lambda expression, and my question is regarding validation of two for loop execution in List Comp: How to make a flat list out of list of lists?
It works left to right and is the short form of:
vec = [[1,2,3], [4,5,6], [7,8,9]]
flatten = []
for elem in vec:
for num in elem:
flatten.append(num)
This will give you the same output as [num for elem in vec for num in elem].
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You are right about it being left to right. It's true when you look at the equivalent too (because of indentation):
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
output = []
for elem in vec: # first layer
for num in elem: # second layer
output.append(num)