I was doing some exercises in python python and I bumped into a problem. I already printed a list reversed and I wanted to print the reversed elements in separate lines too but for some reason it only prints the first one and if I put the first print into comment it prints out the loop just fine. Why?
def main():
pass
if __name__ == '__main__':
main()
list1 = [10, 20, 30, 40, 50]
def reverse_list(l1):
l2 = []
for i in range(len(l1)):
l2.append(l1.pop())
return l2
print(reverse_list(list1))
pass
def reverse_print(l):
listr = reversed(l)
for j in listr:
print(j)
reverse_print(list1)
print("Complete...")
In python, data types are divided into mutable and immutable types:
Mutable object: the value in the memory pointed to by the object can be changed
Immutable object: The value in the memory pointed to by the object cannot be changed, so when the value pointed to by the variable changes, it is equivalent to copying the original value and storing it in a new address, and the variable points to this new address.
a = [1,2,3,4]
a_ref = a
print(a) # [1,2,3,4]
a_ref[0] = 5
print(a) # [5,2,3,4]
It can be seen from the above code
a, a_ref are exactly the same
a and a_ref have the same memory location
modification to a_ref, a will also be changed
for example:
a = [1,2,3,4]
def somefunc(a2):
a2.append(5)
print(a) # [1,2,3,4]
somefunc(a)
print(a) # [1,2,3,4,5]
Normally, it won't change a by calling somefunc(a)
BUT
Since a2 is a reference to a and points to the same memory location, when a2 is modified, it will also be modified to a
in your code:
when you calling reverse_list(list1), l1 is a reference to list1, when you pop the element from l1, it will also pop the element in list1
so after called reverse_list(list1), list1 is empty, that why reverse_print(list1) do not print anything
Sollution
def reverse_list(l1):
l1_copy = l1[:] # copy the whole list
l2 = []
for i in range(len(l1_copy)):
l2.append(l1_copy.pop())
return l2
when you call l1_copy = l1[:]
than l1_copy won't point to same memory location
so l1 and list1 won't modified when modifica l1_copy
PS: english is my second langage, so there maybe have some gramma mistake, please excuse me
at the second print list1 has been emptied out from using the pop() method in reverse_list.
to reverse a list perhaps you should use the reverse()method like the following example:
List1 = [1,2,3]
List1.reverse()
print(List1) # [3,2,1]
``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)}
Below is non-working and working code which generates a list of lists.
Example 1 does not work correctly, it repeats the last list appended over and over.
Example 2, where I replaced delete with creating a new list does work correctly.
# Example 1, this does not work correctly
l1 = []
l2 = []
x = 0
for n in range(0,3):
del l1[:] # deleting all list elements
for i in range(0,3):
l1.append(x)
x+=1
l2.append(l1)
print(l2)
# Example 2, this works correctly
l2 = []
x = 0
for n in range(0,3):
l1 = [] # creating the list each loop through
for i in range(0,3):
l1.append(x)
x+=1
l2.append(l1)
print(l2)
In your first example, l1 is the same list object the entire time. When you do l2.append(l1), you insert a reference to this l1 object into l2. When the loop restarts and you delete everything in l1, you also delete everything in the list inside l2, because that is the same list. You are appending the same list object to l2 multiple times, so every time you clear it, you clear every list in l2.
In the second example, you create a separate list object every time. Each list object is thus independent, and clearing one doesn't affect the others.
Visualization of #1 code - http://goo.gl/6ICqo
l2 and l1 refer to the same object (list). When you delete all the elements of the list, the change is reflected in l2 and l1.
Visualization of #2 code - http://goo.gl/fkoqh
Here, when the code executes l1 = [], l1's reference gets re-assigned. But l2's elements keep referring to the original object.
I have a list that I add items to as the program runs and I have created a copy of this list so I can change/modify/examine the copy WITHOUT changing the original.
This is what I've got so far:
import copy
originallist.append(stuff)
combined=''.join(originallist)
copyoriginal=copy.deepcopy(originallist)
##this didnt work as copyoriginal stayed empty [] while originallist would change.
#i also tried
copyoriginal=list(originallist)
#AND
copyoriginal=originallist[:]
#and with both cases copyoriginal remained at [] while originallist would change!!
Why does it not change?
A copy of the list will not follow changes made to the original list; python's list are completely separate from one another once a copy has been made.
What you are trying to do is not possible without custom classes.
If you want to "keep up with changes" to another list, you may want to consider using a simple reference instead of a copy:
a = [1, 2, 3]
b = a # b refers to a
a[0] = 3
print b # prints [3, 2, 3]
You can always make a copy later when you decide you want to stop tracking changes:
b = b[:]
If you want to names to refer to the same object you can do this:
a = b = []
a.append(1)
b.append(2)
print(b)
# returns [1,2]
That won't let you change one of them without affecting the other, but it will let you see changes in either.
I need to make a copy of a list from a list of lists. The following code gives an error message:
y = list[x]
TypeError: unsubscriptable object
a = [[0],[1]]
for x in a:
y = list[x]
print y
What am I doing wrong here?
y = list[x]
Are you sure you aren't meaning to call the list constructor with the variable x as a parameter, instead of trying to access the element 'x' in the variable 'list'?
As in:
y = list(x)
y=list(x)
The above one should work fine
list is actually the type, so it makes no sense to try and get its x element. If you want to instantiate a list, you need to use list(iterable).
Now, if you want to copy a list, the simpler solution would be to use the copy module.
import copy
a = [[0],[1]]
new_list = copy.copy(a[0])
Pay attention to the fact that if you want to copy an item with nested elements, you'll have to use copy.deepcopy.