-1

I defined the following function:

def myFunction(a):
  print(f'In function, initial a = {a}, {id(a)}, {type(a)}')
  a = a*10
  print(f'In function, final a = {a}, {id(a)}, {type(a)}')
  return a

When I try calling it like so:

a_list_var = [3]
print(f'In main script, initial a_list_var = {a_list_var}, {id(a_list_var)}, {type(a_list_var)}')
myFunction(a_list_var)
print(f'In main script, final a_list_var = {a_list_var}, {id(a_list_var)}, {type(a_list_var)}')

I get this result:

In main script, initial a_list_var = [3], 139940245107776, <class 'list'>
In function, initial a = [3], 139940245107776, <class 'list'>
In function, final a = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], 139940654735936, <class 'list'>
In main script, final a_list_var = [3], 139940245107776, <class 'list'>

As far as I understand, function arguments in Python get passed "by reference". Since lists are mutable objects, I expected a_list_var to get altered in-place after calling myFunction(). But in this case, looking at the ids of a_list_var and a, it seems like a_list_var got passed "by value". Why?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Kanika
  • 1
  • 3
  • 1
    It doesn't. Python arguments are passed by assignment. Which means you will get a reference to the object, but reassigning the variable in the function does not effect the outer namespace. Also you just throw away the return value. – Klaus D. Jul 08 '23 at 08:36

2 Answers2

0

Your function, myFunction, returns the repetition of the list argument a. However, you did not assign the returned list to a_list_var. You can try this:

def myFunction(a):
  print(f'In function, initial a = {a}, {id(a)}, {type(a)}')
  a *= 10 # This is a short for "a = a * 10"
  print(f'In function, final a = {a}, {id(a)}, {type(a)}')
  return a
a_list_var = [3]
print(f'In main script, initial a_list_var = {a_list_var}, {id(a_list_var)}, {type(a_list_var)}')
a_list_var = myFunction(a_list_var)
print(f'In main script, final a_list_var = {a_list_var}, {id(a_list_var)}, {type(a_list_var)}')

What I changed is, I assigned the returned list to the list a_list_var, which results in the following output:

In main script, initial a_list_var = [3], 22569753494784, <class 'list'>
In function, initial a = [3], 22569753494784, <class 'list'>
In function, final a = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], 22569752701824, <class 'list'>
In main script, final a_list_var = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], 22569752701824, <class 'list'>
-1

I'm new to this and trying to figure it out too but if I'm not wrong (and someone can correct me on this),

myFunction is creating a local variable a and modifying the contents of that local variable and returning it within the function window but none of this exists in the global window.

Could you try something like this instead:

a_list_var = myFunction(a_list_var)

print(f'In main script, final a_list_var = {a_list_var}, {id(a_list_var)}, {type(a_list_var)}')

I think it should solve your issue? I don't have access to a computer right now to try this and it might be wrong. But the key thing here is for pass-by-reference to work you must be modifying the argument in-place. Because you are essentially creating a new local variable and pointing it to the argument, the output of myFunction(a_list_var) will not modify whatever the original a_list_var is pointing to.

You could also try redefining myFunction to be:

def myFunction(a):
  nonlocal a_list_var
  a_list_var = a*10

In my example above, I've specified myFunction to modify the global variable a_list_var so that might work instead (since it's not creating a local instance of anything)

gh0st
  • 1
  • 3