1
liste=['a','b','c']
for x in liste :              
       liste_bis=['a','b','c']       
       liste_bis.remove(x)
       print(liste_bis)
       print(liste)

print(" ")

for x in liste :              
       liste_bis=liste    
       liste_bis.remove(x)
       print(liste_bis)
       print(liste)

I really don't understand what is the difference between these loops. The first one does not change liste (only liste_bis) while the second one changes liste (and I never wanted that). Can someone explain to me why?

jkdev
  • 11,360
  • 15
  • 54
  • 77
Vrael
  • 13
  • 3
  • This will help you work out what's going on: [How do I pass a variable by reference?](https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – Shadow Jul 29 '19 at 22:49
  • "_the first one does not change liste_" Because all you did was print it. In the 2nd one you make both variables point to the same thing. – takendarkk Jul 29 '19 at 22:50
  • Hi, Vrael and welcome to SO! The reason of what is happening in the second `for` loop is that you are *copying* `liste` to `liste_bis` in a _weak_ way. Therefore, when something is removed from `liste_bis`, is removed from `liste` because they point to the same location in memory. Have a look at the `copy` module: https://docs.python.org/3.7/library/copy.html – David Jul 29 '19 at 22:55
  • This post could be of your interest, too: https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list – David Jul 29 '19 at 22:57
  • @David there is **no copying occuring at all**, that's the problem – juanpa.arrivillaga Jul 30 '19 at 01:50

2 Answers2

2

The first loop assigns liste_bis a new value at every iteration. So at the beginning of each iteration liste_bis will be always the same.

liste_bis = liste.deepcopy() would be better to use. liste.deepcopy() copies the content of a list into a variable and makes them independent.

So if you write

liste_bis = liste.deepcopy()

every change on list_bis will not change liste.

In the second loop, it is like you are assigning a new name to liste. Whatever is liste now is also liste_bis. Every change in liste_bis will be done on liste and vice versa.

jkdev
  • 11,360
  • 15
  • 54
  • 77
Tony Barletta
  • 375
  • 1
  • 8
  • Thanks a lot! But why does lists behave like that and not variables (as far as I know) ? – Vrael Jul 29 '19 at 22:59
  • 2
    @Vrael All variables in Python are references like that, it's just some values can't be changed—only replaced. When you assign, say, `1` to a number, it is a reference to an object, but that object can't change. The difference is the list can change, so you can notice that two variables point to the same object. In short: assignment (`a = 1`) is like putting the name tag `a` onto `1`, while mutation (`a.remove(...)`) is like picking up the thing with the name tag `a` on and manipulating it. The big trick is that two name tags can be on the same thing, so changes to one affect the other. – Gareth Latty Jul 29 '19 at 23:01
  • I think it is an implementation choice. Whoever design Python decided that it was smarter to do so. Imagine if you had 200k element in the list. By making `deepcopy` as default the system would copy that very big array every time we assign it to a new variable. In this way, programmers will have to explicitly say to copy it entirely. I am not sure about that but seems to be the most reasonable thing to do. – Tony Barletta Jul 29 '19 at 23:04
0

In this case you try to iterate over items of liste so you can make action on them respectively.

First loop you have two list but their value same so you try yo remove item of second list while iterating first one, that is why the first list does not change.

If you need to item length to iterate you can use;

for x in range(len(liste)):
    #evaluations...