I'm trying to understand how a list is treated when passed as an argument to a function. So what I did was the following:
I initialized a list:
ll = [1,2,3,4]
and define a function:
def Foo(ar):
ar += [11]
I passed the list to the function:
Foo(ll)
and when I print it I got:
print ll # [1, 2, 3, 4, 11] #case(1)
So far so good.
Now I modified the function in order to reset the list such that it has a single element only:
def Foo(ar):
ar = [11]
I recalled the syntax:
Foo(ll)
and when I reprint it, it resulted in the same list:
print ll # [1, 2, 3, 4] # case(2)
I thought the list was passed as reference; so whatever we do to the list inside a function will always change the original function passed from the main program. So for case(2) I was expecting the following result:
print ll # [11] # case(2) expected result
Am I missing something here?
You have to make the difference between the object and the name of the object. Lists in Python are mutable objects, so they can be changed whenever you have a reference to it.
Names are just references to objects. Remember that technically in Python there are not variable, just names and objects, and objects are bound to names.
So, with that in mind, let's see your code:
def Foo1(ar):
ar += [11]
This function takes a list, binds it to the local name ar
and then modifies the list, adding a new value.
However this other code:
def Foo2(ar):
ar = [11]
This function takes a list, bound to the ar
name, and then rebinds the name ar
to a new list with one value. The original object is unmodified and fogotten, inside this function.
Then when you do:
a = [1,2,3]
And then call:
Foo1(a)
that modifies the list adding a new value, but:
Foo2(a)
does nothing to the value of a
.
If you want to write a function that replaces all the content of the list with another, you can do that with:
def Foo3(a):
a[:] = [11]
This code does not rebind a
but modifies the list by replacing the content with the new list.
To further illustrate my point, look at this example:
a = []
b = []
c = a
a.append(1)
b.append(2)
c.append(3)
print a
print b
print c
It will print:
[1, 3]
[2]
[1, 3]
Can you to tell why?
ar += [11]
is not just an assignment. It's a method call (the method called is: __iadd__
). when Python executes that line it calls the method and then assigns ar
to the result. The __iadd__
method of list
modifies the current list
.
ar = [11]
is an assignment and hence it simply changes the value of the local name ar
. But there is no link between the ar
name inside the function and the value of the ll
variable.
You probably want something like:
ar[:] = [11]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With