Change a argument value of a function without returning

Hi,

I am surprised to find that:

x3 = 2
y3 = 5
def test3(x, y):
    y += x 
test3(x3, y3)
print(y3)

gives me

5

I expect 7. I can get 7 by doing:

x3 = 2
y3 = [5]
def test3(x, y):
    y[0] += x 
test3(x3, y3)
print(y3[0])

output:

7

Why? What’s the difference between the two data type, integer and array?
Is there any simple way to get 7 without recourse to a list?

Thanks!!

The difference is between mutable objects, which can change in place, and immutable objects, which are fixed and cannot change, only be replaced with a new object.

Integers are immutable. So the statement:

y += 2

takes the existing object named y, 5, adds 2 to give a new object 7, and assigns it to the name y.

Any other names that also refer to the original object 5, like your global variable y3, are unchanged: they still refer to the same object 5.

However, lists (not called arrays!) are mutable, so they can change. In particular, when you assign to a index in a list, the list gets modified, it does not create a whole new list.

So your statement:

y[0] += 2

goes through these steps:

  • look up the name y, which gives you the list [5];

  • look up the item in position 0 of that list, which is the int object 5;

  • add 2 to that int, which gives you a new int, 7 (remember ints are immutable);

  • assign that new int to position 0 of the original list (lists are mutable).

The end result is that y is now the same list as before, just with different contents.

And because it is the same list, other names that refer to it will see the same change. So your global y3 is also affected.

If you are looking for “output parameters” like some languages have,e.g. Pascal calls them “var parameters”, I am afraid you are out of luck. Python does not have output parameters and you cannot get this to work:

def function(inarg, outarg):
    return inarg + 1
    outarg = "success"

a = 99
b = 0
result = function(a, b)  # result will be 100
if b != "success":
    print("something went wrong")  # This prints.

You can simulate the effect with a list, as you have discovered, but that’s all.

Instead we return multiple values:

def function(arg):
    return (arg + 1, "success")

a = 99
result, b = function(a)  # result will be 100
# and b will be "success"
1 Like

Hello, Mr. @steven.daprano. This is just a feedback to your respond.
Your explanations were very detailed and nice. But according to my basic understanding of Python, line 3 is never executed below(is it?):

Python does not have output parameters and you cannot get this to work:

def function(inarg, outarg):
    return inarg + 1
    outarg = "success"#line 3

And, b will never be “succes” -It mustn’t, but this way may be confusing.- because it is an after-return expression. You may want to edit your example to make it more qualified.-Sorry if I am wrong.

Hi Sandra,

You are correct, in standard Python line 3 setting outarg would never be reached. But even if you swap the two lines the assignment will not work as an “output parameter”.

Sorry for any confusion.

1 Like