简体   繁体   中英

Using remove() and append() on a list using a for loop in Python

When I run the following code and print "array" and "main", I am getting the same answer as "main" and "array". I am only modifying "main" but why is it affecting "array" as well. Can anyone help ?

array = ["a",0,0,"b","c","d",0,1,0,1,0,3,0,1,9,0,0,0,0,9]
main = array



for i in range(0,len(main)-1):
   if main[i] == 0 or main[i] == 0.0:
       main.pop(i)
       main.append(0)


print main
print array

In python variables are references to an instance in memory. When you do:

main = array

you're assigning to main a reference to the same instance, that you can check with:

print(id(main))
print(id(array))

when you mutate a list you're iterating over, you're opening the door to scary and awful issues.

Your solution, as stated in a comment is to make a copy of the list:

main = array[:]

which is a shorter equivalent of:

main = []
for elt in array:
    main.append(array)

meaning that the instances in the list are the same in both list, but the container is different.

But because that solution would mean you iterate twice over the list (once to make a copy, and a second time to change the values), a better way would be to actually iterate over a list, and then create a second list as you go:

main = []
for item in array:
   if item in (0, 0.0):
       main.append(0)
   else:
       main.append(item)

Nota Bene: In your snippet you're using the following way to iterate over your list:

for i in range(0,len(main)-1):
    # use main[i]

that's not pythonic at all, instead of that, you just need to use the following more readable syntax:

for item in main:
    # use item

Variables and arrays (they are called "lists" in python) works differently. You are creating only an "alias" in that way. This happens because the two names ("main" and "array") will point out to the same memory address.

To avoid that you have different options:

1) Use copy() function in this way:

main = array.copy()

2) or:

import copy
main = copy.copy(array)

3) using "list" built-in method:

main = list(array)

4) creating a new empy list and extend it:

main = []
main.extend(array)

5) using slicing:

main = array[:]

6) If you are going to create a multi-dimensional list, above example are not enough. In this particular case you need to use deepcopy() function:

import copy
main = copy.deepcopy(array)

Don't modify lists while iterating. Generate a new list:

array = ["a",0,0,"b","c","d",0,1,0,1,0,3,0,1,9,0,0,0,0,9]
main = [x for x in array if x != 0]
main.extend([0] * (len(main)-len(array)))

print main
print array

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM