Why doesn't the + operator change the list while .append () does?

I work through Udacity, and Dave Evans introduced an exercise on list properties.

list1 = [1,2,3,4] list2 = [1,2,3,4] list1=list1+[6] print(list1) list2.append(6) print(list2) list1 = [1,2,3,4] list2 = [1,2,3,4] def proc(mylist): mylist = mylist + [6] def proc2(mylist): mylist.append(6) # Can you explain the results given by the four print statements below? Remove # the hashes # and run the code to check. print (list1) proc(list1) print (list1) print (list2) proc2(list2) print (list2) 

Output signal

 [1, 2, 3, 4, 6] [1, 2, 3, 4, 6] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4, 6] 

Thus, in the function, adding a to the set is not displayed, but does this happen if not in the function?

+7
source share
6 answers

Thus, in the function, adding a to the set is not displayed, but does this happen if not in the function?

No, this is not what is happening.

It happens that when you do mylist = mylist + [6] you actually create a completely new list and put it in the local variable mylist . This mylist variable will disappear after the function is executed, and the newly created list will also disappear.

OTOH, when you execute mylist.append(6) , you are not creating a new list. You get the list already in the mylist variable and add a new element to the same list. As a result, the list (which is indicated by the symbol list2 too) will be changed by itself. The mylist variable will disappear again, but in this case you have changed the original list.

Let's see if a more visual explanation helps you :)

What happens when you call proc()

When you write list1 = [1, 2, 3, 4, 5] , you create a new list object (on the right side of the equal sign) and create a new variable list1 that points to this object.

Creating new list instance and global variable

Then, when you call proc() , you create a new new variable mylist , and since you pass list1 as a parameter, mylist will point to the same object:

Calling method creates local variable

However, the operation mylist + [6] creates a whole new list object, the contents of which are the contents of the object that mylist points mylist , plus the contents of the next list object, that is, [6] . Since you are binding this new object to mylist , our script changes a bit, and mylist no longer points to the same object that list1 points list1 :

mylist points to new list object

I did not say that mylist is a local variable: it will disappear after the proc() function ends. So, when the completion of proc() ended, mylist went away:

mylist is gone

Since no other variable points to the object generated by mylist + [6] , it will also disappear (since the garbage collector * will collect it):

Gc collects the list

Note that at the end, the object pointed to by list1 does not change.

What happens when you call proc2()

Everything changes when you call proc2() . At first it’s the same thing: you create a list ...

Creating new list instance and global variable

... and pass it as a parameter to the function that will generate the local variable:

Calling method creates local variable

However, instead of using the concatenation operator + , which generates a new list, you apply the append() method to the existing list. The append() method does not create a new object; instead, it changes the existing one:

Appending a value to a list

After the function finishes, the local variable will disappear, but the original object that it points to and list1 will already be changed:

It is still altered

Since it is still listed by list1 , the original list is not destroyed.

EDIT : if you want to take a look at all this that happens before your eyes , just go to this radically amazing simulator :

enter image description here

* If you do not know what a garbage collector is ... well, you will immediately know your own question.

+15
source

Variables in python can always be considered as links. When you call a function with an argument, you pass a reference to the actual data.

When you use the assignment operator ( = ), you assign this name to indicate a completely new object. Thus, mylist = mylist + [6] creates a new list containing the old contents of mylist, as well as 6 and assigns the variable mylist to refer to the new list. list1 still points to the old list, so nothing changes.

On the other hand, when you use .append, it actually adds the item to the list the variable belongs to - it does not assign anything new to the variable. Thus, your second function modifies the list referenced by list2.

+3
source

Usually, in the first case, in the proc function, you could change the global list as intended if you declared

 global mylist 

and did not pass mylist as a parameter. However, in this case, you will receive an error message that mylist is global and local: name 'mylist' is local and global . What happens in proc is that when the assignment is done, a local list is created. Since local variables disappear when the function ends, the effect of any changes in the local list does not apply to the rest of the program when it is subsequently printed.

But in the second proc2 function proc2 you modify the list by adding it, rather than assigning it, so the global not required, and changes to the list are displayed elsewhere.

+2
source

This, in one form or another, is a very common question. I tried to explain the Python parameter by passing me a couple of days ago . In principle, one of them creates a new list, and the other modifies the existing one. In the latter case, all variables that refer to the list β€œsee” the change, since it is still the same object.

0
source

In the third line you did it

 list1=list1+[6] 

So, when you did the following after the specified line,

 print (list1) 

which printed the list1 that you created at the beginning and the proc procedure, which adds list1 + [6], which creates a new list inside the proc function. Where, as when adding [6], you do not create a new list, but add a list item to an existing list.

But keep in mind. On line 7, you created the list again

 list1 = [1,2,3,4] 

Now you want to print list1, calling it explicitly, which will print list1, which you reinitialized, but not the previous one.

0
source

As well as comprehensive answers, it's also worth knowing that if you want to have the same syntax as:

 mylist = mylist + [6] 

... but still want the list to be updated "in place", you can do:

 mylist += [6] 

Which, although it looks like it will do the same as the first version, is actually the same as:

 mylist.extend([6]) 

(Note that extend takes the contents of the iteration and adds them one at a time, while append accepts everything it is given and adds it as a single element. See append vs. extend for a full explanation.)

0
source

All Articles