0

I am currently new to python and I'm still learning the basics, but there is one thing I just can't wrap my head around. Why is the code in Q.1 giving the out-print 3, while Q.2 is giving the out-print [4]? When asked, I was told that the f(x)-line at the bottom of Q.1 isn't given any variable or box to hold the new return-value given from the def. and that's the reason why the out-print of x remain 3. This made sense to me, but then why would the out-print in Q.2 equal the return-value of g(x)? There isn't any variable or box to contain the return-value of x in this code either..

Q.1:

def f(x):
    x += 1
    return x
x=3
f(x)
print(x)

Q.2:

def g(x):
    x[0] = x[0] + 1
    return x
x = [3]
g(x)
print(x)
Gayal Kuruppu
  • 1,261
  • 1
  • 17
  • 29

4 Answers4

1

A Python function takes arguments by reference (something that points to the real object) whenever that argument is "complex", and takes the argument by value (a copy of the item) when it's a simple thing.

Q.1 is taking an int as an argument, then the function creates an internal copy of it and thus does not modify the value of x outside the function.

Q.2 is taking a list as an argument, which is considered complex, in which case the function takes a reference to the original and whatever happens to that reference will also happen to the original.

You can find an explanation of pass-by-reference and pass-by-value with images here

Piero Hernandez
  • 435
  • 4
  • 10
0

In Python, lists are mutable objects, and as a result they are passed-by-reference when used in a function call. This means that when g(x) adds 1 to the first element of x, after the function exits, the original list x will contain those changes.

Note that the specific term used is not "pass-by-reference", but rather "pass-by-name", which comes with a couple different semantics, which you can learn more about if you wish.

Tyler Yep
  • 37
  • 6
0

The function defined is Q1 is returning a value of for. x contains 3 and is passed into the function, by calling it with f(x). It gets incremented and returned to the function call. But, the function call was not stored in a variable, so it was not saved into memory. Nothing was done with the returned value. Calling the function is only editing the variable x within the local scope (within the function). When you're using print(x) it is referencing the global variable of x, which still contains 3.

In Q2, lists are mutable. Editing them within a function, the changes persist in the global scope. Because that list is mutated in the global scope, using print(x) uses the updated global variable.

I hope this makes sense. Look into scope of variables in the documentation for more.

Brenden Price
  • 517
  • 2
  • 9
0

Q1

def f(x):
    x += 1
    return x
x=3
f(x)
print(x)

The reason this is returning 3 and not 4 is because you haven't rebound your variable to reference this new value. Instead of f(x) you can do x = f(x).

Q2

def g(var):
    var[0] = var[0] + 1
    return var
x = [3]
g(x)
print(x)

To answer this without making it confusing I've changed the local variable used in the function to var so you can see what I'm trying to explain to you easier.

First you are creating a list with a integer value 3 in the first spot in the list (element 0) and you make x reference this list.

When you call g() function and pass the list, the function sets var to reference the same list (not a different one, the same one). You then tell the function to increase the integer value in the first element by 1. Since lists are mutable with certain methods, you have already changed the list for both the local variable var, and the global variable x. This means that you actually don't need to use any return of the function because the list has been mutated in place.

Have a look at this video https://youtu.be/_AEJHKGk9ns where Ned Batchelder explains more about this.

nheme87
  • 26
  • 2