Reputation: 3495
I'm working through Udacity and Dave Evans introduced an exercise about 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)
The output is
[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]
So in a function the adding a 6 to the set doesn't show but it does when not in a function?
Upvotes: 10
Views: 4267
Reputation: 27050
When you execute mylist = mylist + [6]
, you're actually creating an entirely new list and assigning it to the local variable mylist
. This local variable mylist
will disappear after the function completes, and the newly created list will also vanish.
On the other hand, when you execute mylist.append(6)
, you don't create a new list. Instead, you modify the existing list that mylist
is pointing to by adding a new element to it. This change is reflected in the original list (which list2
also points to). The mylist
variable will still disappear after the function ends, but in this case, the original list remains altered.
Let's break this down visually:
proc()
When you write list1 = [1, 2, 3, 4, 5]
, you're creating a new list object (on the right side of the equals sign) and assigning it to a new variable, list1
, which points to this object.
When you call proc()
, a new variable mylist
is created. Since you pass list1
as a parameter, mylist
points to the same object:
However, the operation mylist + [6]
creates a new list object that combines the elements of the object pointed to by mylist
with [6]
. Since this new list is assigned to mylist
, the situation changes, and mylist
no longer points to the same object as list1
:
Remember, mylist
is a local variable that will disappear after proc()
ends. So, when the function execution is complete, mylist
is gone:
Since no other variable points to the object created by mylist + [6]
, it will disappear too (collected by the garbage collector):
Notice that in the end, the object pointed to by list1
is not changed.
proc2()
The scenario changes when you call proc2()
. Initially, it's the same: you create a list...
...and pass it as a parameter to a function, which generates a local variable:
However, instead of using the +
operator (which generates a new list), you use the append()
method. The append()
method does not create a new object; it modifies the existing one:
After the function ends, the local variable will disappear, but the original list pointed to by both mylist
and list1
remains altered:
Since list1
still points to this list, the original list is not destroyed.
EDIT: If you want to see all of this in action, check out this amazing simulator:
* If you're unfamiliar with garbage collection, you'll soon understand it better after grasping this concept.
Upvotes: 19
Reputation: 931
As well as the comprehensive answers already given, it's also worth being aware that if you want the same looking syntax as:
mylist = mylist + [6]
...but still want the list to be updated "in place", you can do:
mylist += [6]
Which, while it looks like it would do the same thing as the first version, is actually the same as:
mylist.extend([6])
(Note that extend
takes the contents of an iterable and adds them one by one, whereas append
takes whatever it is given and adds that as a single item. See append vs. extend for a full explanation.)
Upvotes: 2
Reputation: 534
In the third line, you did this
list1=list1+[6]
So, when you did the below after the above line,
print (list1)
which printed list1 that you created at the start and proc procedure which adds list1 + [6] which is creating a new list inside the function proc. Where as when you are appending [6], you are not creating a new list rather you are appending a list item to already existing list.
But, keep in mind. In line 7, you again created the list
list1 = [1,2,3,4]
Now you wanted to print the list1 by calling it explicitly, which will print out the list1 that you reinitialized again but not the previous one.
Upvotes: 0
Reputation: 184091
This, in one form or another, is a very common question. I took a whack at explaining Python parameter passing myself a couple days ago. Basically, one of these 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 because it's still the same object.
Upvotes: 0
Reputation: 143047
Ordinarily, in the first case in function proc
you would only be able to change the global list by assignment if you declared
global mylist
first and did not pass mylist
as a parameter. However, in this case you'd get an error message that mylist
is global and local:
name 'mylist' is local and global
. What happens in proc
is that a local list is created when the assignment takes place. Since local variables go away when the function ends, the effect of any changes to the local list doesn't propagate to the rest of the program when it is printed out subsequently.
But in the second function proc2
you are modifying the list by appending rather than assigning to it, so the global
keyword is not required and changes to the list show elsewhere.
Upvotes: 2
Reputation: 7187
Variables in python can always be thought of as references. When you call a function with an argument, you are passing in a reference to the actual data.
When you use the assignment operator (=
), you're assigning that name to refer to an entirely new object. So, 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 is still pointing to the old list, so nothing changes.
On the other hand, when you use .append, that is actually appending an element to the list that the variable refers to - it is not assigning anything new to the variable. So your second function modifies the list that list2 refers to.
Upvotes: 3