5

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()
2
  • 4
    Lists are mutable, you can modify their elements and it affects everyone with a reference. When you re-assign it, you're creating a new reference. Commented Jul 7, 2017 at 13:23
  • It's quite weird how I refer to other pieces of code as "everyone". Maybe humanising code is my way of understanding it better. Commented Jul 7, 2017 at 13:24

5 Answers 5

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

4 Comments

As far as scope goes, the functions in my example have access to the input parameters, local and global variables. If an argument is mutable, then a function can change it's values by reference, and in turn, those changes happen outside the scope of the function (correct me if I'm wrong, or inaccurate).
Yes, everything you said is pretty much correct. The only comment I would make is that variables are not global by default. See here for more details.
Ok, so when I'm reviewing code, I'll also keep in mind if an input parameter is mutable or not. Thank you for your help!
Glad to help @shoe02.
1

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.

Comments

0

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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.