Reputation: 315
I have a question about the scope in python functions. I've included an example that demonstrates the issue I am having.
fun0 redefines the first entry in varible c's list. This change is reflected outside of fun0, even when I don't return any values from fun0.
fun1 redefines the variable c entirely, but the change isn't reflected outside of fun1. Similarly, fun2 redefines c, and the change isn't reflected outside of fun2.
My question is, why does fun0 modify val3 in the main function, while fun1 and fun2 don't modify val4 and val7, respectively?
def fun0(a, b, c):
c[0] = a[0] + b[0]
return
def fun1(a, b, c):
c = a[0] + b[0]
return
def fun2(a, b, c):
c = a + b
return
def main():
val1 = ['one']
val2 = ['two']
val3 = ['']
fun0(val1, val2, val3)
print val3
val4 = []
fun1(val1, val2, val4)
print val4
val5 = 1
val6 = 1
val7 = 0
fun2(val5, val6, val7)
print val7
return
if __name__=='__main__':
main()
Upvotes: 5
Views: 439
Reputation: 589
as said before, lists are mutable. If you pass a list and modify it, you do it everywhere.
This applies for all lists in fun0
.
in fun2
you pass no lists and and therefore c
is calculated within fun2
, but not available on the outside.
I'm not sure about fun1
, but i think you are overwriting c
with a new variable that is not available on the outside as in fun2
.
Upvotes: 0
Reputation: 3965
Technically when you pass an argument to a function you are passing a copy, not the original. Now there is a difference between passing a list and passing variable. A list holds a reference to other object while a variable holds a value. Therefore when passing a list even if it gets copied it still is referencing the same objects and can be changed within the function, but when passing a variable the copied object has nothing to do with the original. Hope this make sense.
Upvotes: 1
Reputation: 570
What Cary Shindell is absolutely correct. Furthermore, if you DID want to save the updated values, here is how you can change your code to do that, I changed the print statements since I tested this in python 3.6.1. Good question though.
def main():
val1 = ['one']
val2 = ['two']
val3 = ['']
fun0(val1, val2, val3)
print(val3)
val4 = []
val4 = fun1(val1, val2, val4)
print(val4)
val5 = 1
val6 = 1
val7 = 0
val7 = fun2(val5, val6, val7)
print(val7)
return
Upvotes: 0
Reputation: 22953
My question is, why does fun0 modify val3 in the main function, while fun1 and fun2 don't modify val4 and val7, respectively?
This is because of the way Python passes arguments.
When you pass arguments to a function, Python passes them by assignment.This means it binds the argument references to the parameter names. That's the only way the parameter and argument names are related. In your first example, you simply passed a reference to val3
, and since both val3
and c
were referring to the same list object, the changes were reflected across both names.
However, when you reassigned c
inside of your functions, you replaced the reference to the lists c
was holding and reassigned c
a new reference.
Upvotes: 1
Reputation: 1386
It has to do with the way lists and variables are stored. You can modify a list within a function because they are mutable objects. However, if you do c = a[0] + b[0]
, you are creating a local variable within fun1
and fun2
, which stays within the function scope.
Upvotes: 2