I have this snippet of code:
list1 = [1, 2, 3]
list2 = list1
list1 = [4, 5, 6]
print(list2)
print(list1)
Which results in the following output:
[1, 2, 3]
[4, 5, 6]
Why is list2 not still pointed to [4, 5, 6]? I was under the impression that, since lists are mutable, the change would affect both list1 and list2, since in RAM both lists are pointed to the same sequence of items.
Any explanation would be appreciated.
I have added the reason as comments in the code :
# list1 variable points to the memory location containing [1, 2, 3]
list1 = [1, 2, 3]
# list2 variable made to point to the memory location pointed to by list1
list2 = list1
# list1 variable made to point to the memory location containing
# a new list [4, 5, 6], list2 still pointing to [1, 2, 3]
list1 = [4, 5, 6]
print(list2) # list2 prints [1, 2, 3]
print(list1) # list1 prints [4, 5, 6]
I'll go through the lines one by one:
# Define a list [1, 2, 3] and save it into list1 variable
list1 = [1, 2, 3]
# Define list2 to be equal to list1 (that is, list2 == list1 == [1, 2, 3])
list2 = list1
# Create a new list [4, 5, 6] and save it into list1 variable
# Notice, that this replaces the existing list1!!
list1 = [4, 5, 6]
# Print list2, which still points to the original list [1, 2, 3]
print(list2)
# Print the new list1, [4, 5, 6] that is
print(list1)
However, this:
list1 = [1, 2, 3]
list2 = list1
list1.append(4)
print(list2)
print(list1)
Will output:
[1, 2, 3, 4]
[1, 2, 3, 4]
Since we are editing the list1 (and therefore list2, they are mutable), not creating a new list and saving it under the variable name list1
The keyword here is create a new list, so you're not editing list1 in your example, you're actually changing the name list1 to point to a whole different list.
Lists are mutable. However, the line:
list1 = [4, 5, 6]
does not mutate the list object previously referenced by list1, it creates a brand new list object, and switches the list1 identifier to reference the new one. You can see this by looking at object IDs:
>>> list1 = [1, 2, 3]
>>> list2 = list1
>>> id(list1)
4379272472
>>> id(list2)
4379272472 # both reference same object
>>> list1 = [4, 5, 6]
>>> id(list1)
4379279016 # list1 now references new object
>>> id(list2)
4379272472 # list2 still references previous object
Related
I'm very new in python. I just stuck in one problem.
I have two lists, like -
list1 = [1,2,3,4,5]
list2 = [3,6,8,9,1,2,4,0,5]
Now I have to check each value of list1 with that it is present in list2 or not. If all the value of list1 is present in list2 then update the list2 by removing extra values from list2. So list2 will be like -
list2 = [3,1,2,4,5]
Tried to do this with nested loop. but it is reading only 1st value. how can I do that?
One of the many options for performing the task
list1 = [1, 2, 3, 4, 5]
list2 = [3, 6, 8, 9, 1, 2, 4, 0, 5]
list2 = [num for num in list2 if num in list1 and set(list1).issubset(list2)]
I am trying to append a list of lists with Python but there is an error. My problem is just with append function. I explain my problem better. I am using a loop. The first time the append function works fine. But for the second time, the function does not work.
When we do the first loop, we get the right result:
list1 = [1,2,3]
list2 = [4,5,6]
list3 = []
list3.append(list1)
list3.append(list2)
print(list3)
result:
[[1, 2, 3], [4, 5, 6]]
With the second loop, append does not work correctly. One extra bracket.
liste4 = []
liste4.append(list3)
liste4.append(list1)
print(liste4)
result:
[[[1, 2, 3], [4, 5, 6]], [1, 2, 3]]
But the result I want is this:
[[1, 2, 3], [4, 5, 6], [1, 2, 3]]
Define list3 as an empty list and append to it :
list1 = [1,2,3]
list2 = [4,5,6]
list3 = []
list3.append(list1)
list3.append(list2)
print(list3)
Output :
[[1, 2, 3], [4, 5, 6]]
you could just do list3 = [list1, list2]
If you want it in a function, here is a go a a List of List creator, which may take multiple lists as the input:
def LoL(*lists):
out = [x for x in lists]
return out
list1 = [1,2,3]
list2 = [4,5,6]
list3 = [7,8,9]
list4 = LoL(list1,list2,list3)
list4
>>> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
list1 = [1,2,3]
list2 = [4,5,6]
list3 = []
list3.append(list1)
list3.append(list2)
print(list3)
result:
[[1, 2, 3], [4, 5, 6]]
With the second loop:
liste4 = list3
liste4.append(list1)
print(liste4)
result:
[[1, 2, 3], [4, 5, 6], [1, 2, 3]]
I would like to create a new nested list from an already existing nested list. This new list should include the indices+1 from the existing list.
Example:
my_list = [[20, 45, 80],[56, 29],[76],[38,156,11,387]]
Result:
my_new_list = [[1,2,3],[1,2],[1],[1,2,3,4]]
How can I create such a list?
save a python loop, force iteration of range (required for python 3) in a list comprehension, so it's faster than a classical double nested comprehension:
my_list = [[20, 45, 80],[56, 29],[76],[38,156,11,387]]
index_list = [list(range(1,len(x)+1)) for x in my_list]
There's a few ways to do this, but the first that comes to mind is to enumerate the elements with a starting index of 1 in a nested list comprehension.
>>> [[index for index, value in enumerate(sub, 1)] for sub in my_list]
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
Another solution could be:
new_list = [list(range(1,len(item)+1)) for item in my_list]
Here is are some simple solutions:
>>> lst = [[20, 45, 80],[56, 29],[76],[38,156,11,387]]
>>> out = [[x+1 for x,_ in enumerate(y)] for y in lst]
>>> out
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
>>>
>>>
>>> out = [[x+1 for x in range(len(y))] for y in lst]
>>> out
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
Using nested list comprehension
First you want a list with every number from 1 to the length of your sublist. There are several ways to do this with list comprehension.
For example
[i for i in range(1, len(sublist) + 1)]
or
[i + 1 for i in range(len(sublist))]
Second you want to do this for every sublist inside your my_list. Therefore you have to use nested list comprehension:
>>> my_list = [[20, 45, 80],[56, 29],[76],[38,156,11,387]]
>>> my_new_list = [[i+1 for i in range(len(sublist))] for sublist in my_list]
>>> my_new_list
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
Using list comprehension with range
Another way would be using the range built-in function as a generator for your sublists:
>>> [list(range(1, len(sublist) + 1)) for sublist in my_list]
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
Using map with range
Or you can use the map built-in function
>>> list(map(
... lambda sublist: list(range(1, len(sublist) + 1)),
... my_list
... ))
[[1, 2, 3], [1, 2], [1], [1, 2, 3, 4]]
Is there a function in Python to get the difference between two or more values in a list? So, in those two lists:
list1 = [1, 5, 3, 7]
list2 = [4, 2, 6, 4]
I need to calculate the difference between every value in list1 and list2.
for i in list1:
for ii in list2:
print i -ii
This gives negative values, but I want the subtraction between the values of the two lists only from highest value to lowest value for not getting negative values.
For the above lists, I expect the output to be [3, 3, 3, 3].
Thanks.
Assuming you expect [3, 3, 3, 3] as the answer in your question, you can use abs and zip:
[abs(i-j) for i,j in zip(list1, list2)]
Either zip the lists, or use numpy:
>>> list1 = [1, 5, 3, 7]
>>> list2 = [4, 2, 6, 4]
>>> [a-b for a,b in zip(list1, list2)]
[-3, 3, -3, 3]
>>> import numpy as np
>>> np.array(list1) - np.array(list2)
array([-3, 3, -3, 3])
Remember to cast the array back to a list as needed.
edit:
In response to the new requirement that the absolute values are needed: you can add abs in the list comprehension:
>>> [abs(a-b) for a,b in zip(list1, list2)]
[3, 3, 3, 3]
and the numpy solution would change to:
>>> map(abs, np.array(list1) - np.array(list2))
[3, 3, 3, 3]
You may also do if else condition inside list comprehension.
>>> [i-j if i>j else j-i for i,j in zip(list1, list2)]
[3, 3, 3, 3]
You can use zip method in order combine these two lists. See the tutorials for zip method https://docs.python.org/2/library/functions.html#zip
>>> list1 = [1, 5, 3, 7]
>>> list2 = [4, 2, 6, 4]
>>> [abs(x-y) for x, y in zip(list1, list2)]
[3, 3, 3, 3]
Avinash Raj's answer is correct, or alternatively, using map():
from operator import sub
C = map(sub, A, B)
l = [1, 2]
l.append(l)
>>>l
[1, 2, [...]] #l is an infinite list
Why does this create an infinite list instead of creating:
l = [1, 2]
l.append(l)
>>>l
[1, 2, [1, 2]]
When you do:
l.append(l)
a reference to list l is appended to list l:
>>> l = [1, 2]
>>> l.append(l)
>>> l is l[2]
True
>>>
In other words, you put the list inside itself. This creates an infinite reference cycle which is represented by [...].
To do what you want, you need to append a copy of list l:
>>> l = [1, 2]
>>> l.append(l[:]) # Could also do 'l.append(list(l))' or 'l.append(l.copy())'
>>> l
[1, 2, [1, 2]]
>>> l is l[2]
False
>>>
Easy, because each object will have a reference to itself in the third element. To achieve [1, 2, [1, 2]] then use a copy of the list.
l.append(l[:])