2

I moved from using Matlab to Python and the variable assignment while using functions is confusing me.

I have a code as follows:

a = [1,1,1]

def keeps(x):
    y = x[:]
    y[1] = 2
    return y

def changes(x):
    y = x
    y[1] = 2
    return y

aout = keeps(a)
print(a, aout)

aout = changes(a)
print(a, aout)

The first print statement gives [1, 1, 1] [1, 2, 1], while

the second one gives [1, 2, 1] [1, 2, 1].

I had a understanding (coming from Matlab) that the operations on a variable within a function are local. But here, if I don't make a copy of the variable inside a function, the values change outside the function as well. It's almost as if the variable is defined as global.

It will be very helpful if someone can explain how the variables are allocated differently in both the methods and what are the best practices if one wants to send a variable to the function without affecting it's value outside the function? Thanks.

nish-ant
  • 119
  • 3
  • 15
  • Possibly a duplicate, definitely helpful: https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference – bnaecker Oct 03 '18 at 14:30
  • 1
    Welcome to Python. As you already noticed, not all languages work the same way, so while they usually have common concepts (variables, functions, iterations, conditionnals etc), you'll find out that the implementation of those concepts can be widly different from one language to another, so do not assume that a superficial similarity imply a similar behaviour - IOW, take time to learn the new language without preconception and you'll save yourself a lot of time, pain and frustration. – bruno desthuilliers Oct 03 '18 at 14:49
  • Possible duplicate of https://stackoverflow.com/questions/22054698/python-modifying-list-inside-a-function – tripleee Oct 03 '18 at 15:06
  • Possible duplicate of https://stackoverflow.com/questions/18949904/python-function-is-changing-the-value-of-my-input-and-i-cant-figure-out-why – tripleee Oct 03 '18 at 15:09

2 Answers2

3

Argument passing is done by assignment. In changes, the first thing that happens implicitly is
x = a when you call changes(a). Since assingment NEVER copies data you mutate a.

In keeps you are not mutating the argument list because x[:] is creating a (shallow) copy which then the name y is assigned to.

I highly recommend watching Facts and Myths about Python names and values.

timgeb
  • 76,762
  • 20
  • 123
  • 145
2

Let's look at your code, but first, we will mode the function declarations to the top, so that the order of execution becomes clearer.

def keeps(x):
    y = x[:]  #Here you are creating a modifiable copy of the original x list and referencing it with y
    y[1] = 2
    return y

def changes(x):
    y = x  # Here you are just referencing x itself with a new name y
    y[1] = 2
    return y

a = [1,1,1]

aout = keeps(a)
print(a, aout)

aout = changes(a)
print(a, aout)

Basically if you just assign another variable name to a list, you are giving two names to the same object, so any changes in the contents may affect both "lists". When you use y = x[:]you are in fact creating a new copy of the x list in memory, through list slicing, and assigning the new variable name y to that new copy of the list.

Victor Domingos
  • 1,003
  • 1
  • 18
  • 40