I stumbled upon a theoretical question about how python works, and it got me puzzled. I tried to understand exactly what happened but couldn't find the answer in google - I'm a beginner, so I don't even know the terminology to make the apropriate search.
On the following code, when calling the function it changes myList, while I only wanted to create a list2 which was a copy of list1 (myList).
myList = [1,2,3,4,5,(1,2),(3,4)]
def onlyTuples(list1):
list2 = list1 # here is my question
for index,e in enumerate(list2):
if type(list2[index]) is not tuple:
list2[index] = (list2[index],)
return(list2)
print(myList)
create_new_list = onlyTuples(myList) # triggered by this call
print(myList)
It's all good if I change list2 = list1 to list2 = list(list1) and myList won't be changed when calling the function, but why?
The same thing doesn't happen with something like this:
a = 6
b = a
b = 7
print(a)
Any light upon the question will be appreciated. Thanks!
In python lists are passed by reference, so when you pass list to a function you pass its address in the memory. list2 = list1 won't create a copy of the list, it will save in list2 the address saved in list1. so change of list2 will change list1, but the function in the class list doesn't save the address, it copy a sequence to a list
To make a copy of a list, use:
newList = myList.copy()
I'm trying to convert this for loop into "list comprehension" format if possible:
This loop adds 0 into two dimensional list
test_list = [['string1'],['string2'],['string3']]
for i in range(len(test_list)):
test_list[i].insert(1, 0)
output:
test_list = [['string1',0],['string2',0],['string3',0]]
I've tried this but for some reason it doesn't work.
test_list = [test_list[i].insert(1, 0) for i in range(len(test_list))]
It doesn't work, because list.insert() modifies the list in-place and returns None, so you will end up with a list of Nones which are return values from all .insert()s.
List comprehension format is not adequate for what you want, because it is designed to create new lists, and you seem to want to modify the list in-place. If you want to create new lists instead, you can use this:
test_list = [sublist + [0] for sublist in test_list]
this works because the + operator on lists creates and returns a new list.
Is your question "what's the reason?"
The line
test_list = [test_list[i].insert(1, 0) for i in range(len(test_list))]
means "make a list of the return values of this expression".
The return value of the expression [].insert() is None. test_list will be set to a list of Nones.
for example,i got a list:
mylist = [1,2,3]
we all know append() can add a new item at the end of the list like that:
mylist.append(4)
now the mylist is [1,2,3,4]
my issue is what happened when mylist append itself????
mylist.append(mylist)
at first i think it will look like this:
[1,2,3,4,[1,2,3,4]]
but when i print it, output is [1,2,3,4,[...]],so i print the mylist[5] and it's same to the mylist:[1,2,3,4,[...]]
so you can loop the last item of list endless,and the last item always be the same to original mylist!!!!!
anyone can tell me why is that????????
Because you aren't appending a copy of the list, but the actual list object itself. Consider this program:
mylist = [1,2,3,4]
mylist.append(mylist)
assert id(mylist) == id(mylist[4])
The final item of the list is a reference to the list itself, so you have a fully recursive, self-referential data structure.
If you want the result [1,2,3,4,[1,2,3,4]], then you need to append a copy of the original list, like so:
mylist = [1,2,3,4]
mylist.append(list(mylist))
assert mylist == [1,2,3,4,[1,2,3,4]]
It's doing that because you're telling Python to append a list(my_list) to a list. If you want to extend the list with the contents of the list, you can do this:
new_list = old_list + new_list
output: [1, 2, 3, 4, 1, 2, 3, 4]
or you can use the extend method.
old_list.extend(my_list)
Which will modify the old_list in place.
I have shuffled the list and assigned it to another variable and when I am trying to print it, it is giving output as None? What is wrong ?
list1 = [1,2,3,4,5,6]
list2 = shuffle(list1)
print list2
The random.shuffle() function is designed to take a list and shuffle its contents. It does not return the shuffled list. The documentation states:
Shuffle the sequence x in place.
As such, if you try to assign the return to a variable you will get None.
You can do the following instead:
list1 = [1,2,3,4,5,6]
shuffle(list1)
print list1
If you wish to preserve your original list order:
list1 = [1,2,3,4,5,6]
list2 = list1[::] # make a copy
shuffle(list2)
print list2
Shuffle() function is not accessible directly, so we need to import shuffle module and then we need to call this function using random static object.
#!/usr/bin/python
import random`
list = [1, 2, 3, 4, 5];
random.shuffle(list)
print "list : ", list
``I have a dictionary in python like this.
dictionary = {"00":[1,2,3,4,5,6,7,8,9],"01":[1,2,3,4,5,6,7,8,9],"02":[1,2,3,4,5,6,7,8,9],"03":[1,2,3,4,5,6,7,8,9],"04":[1,2,3,4,5,6,7,8,9]........up-to "99":[1,2,3,4,5,6,7,8,9]}
I have to delete the value 2 from the list of "00".I tried it using following statement.
del (dictionary[key][dictionary[key].index(sudokumatrix[i][iindex])]).
Here key has value "00" and sudokumatrix[i][iindex] has value 2.But i got resulting dictionary as
{"00":[1,3,4,5,6,7,8,9],"01":[1,3,4,5,6,7,8,9],"02":[1,3,4,5,6,7,8,9],"03":[1,3,4,5,6,7,8,9],"04":[1,3,4,5,6,7,8,9].....}.
I have to get the result as:
{"00":[1,3,4,5,6,7,8,9],"01":[1,2,3,4,5,6,7,8,9],"02":[1,2,3,4,5,6,7,8,9],"03":[1,2,3,4,5,6,7,8,9],"04":[1,2,3,4,5,6,7,8,9]....}
I am posting the whole code here:
dictionary = dict()
zerotonine = "123456789"
list2 = list(zerotonine)
list2 = [int(i) for i in list2]
sudokumatrix=[]
for p in range(9):
for q in range(9):
keyis=str(p)+str(q)
dictionary[keyis] = list2
for i in range(9):
initialinput = [1,2,3,4,5,6,7,8,9]
list1=list(initialinput)
list1 = [int(i) for i in list1]
sudokumatrix.append(list1)
key = "00"
del dictionary[key][dictionary[key].index(sudokumatrix[0][1])]
print dictionary
EDIT == I guess(since the generation of dictionary is not given) ==EDIT.
The reason is that the values of keys '00', '01', ... are pointing to the same list. Modifying one of them will definitely affect the others.
Try using this to generate your dict
dictionary = dict((str(x).zfill(2), range(1, 10)) for x in range(100))
Your code of this part is actually not wrong, but to use list.remove() will make it much better.
The issue has to do with pointers.
replace this:
dictionary[keyis] = list2
with this:
dictionary[keyis] = [int(i) for i in list2]
You're creating list2 correctly, but when you go into the loop Python doesn't make a brand new copy of it with every iteration. It makes a pointer to the original list. Python sees:
dictionary[keyis] = list2
and says "oh, list2? I recognize that name! I have that as an object in memory already! I'll save some space by just updating the original copy and linking it here! Any time someone wants to view it or update it I'll just deal with the original and everything will be awesome forever!!!"
OK, so maybe the python interpreter isn't that enthusiastic, but that's how I like to think of it. The end result is that all of your dictionary values are pointing at the original list.
If you don't mind deleting every occurrence of 2 in the list, you can use list comprehension:
dictionary["00"] = [i for i in dictionary["00"] if i != 2]
This will create a new list, and will avoid altering the other values, as it appears all your dictionary values reference the same list.
EDIT: Yep your dictionary values reference the same list
you could use dictionary and list comprehension to create your dictionary
dictionary = {str(x):[i for i in range(10)] for x in range(100)}