1

I am not understanding the difference between these two methods can someone explain? Why in one of them the reference object was changed but in the second one the reference remains unchanged? I come from Java, C# background if that helps. To me it seems like the reference should update in both of them. Thanks

def changeme( mylist ):
   "This changes a passed list into this function"
   mylist.append([1,2,3,4]);
   print "Values inside the function: ", mylist
   return

# Now you can call changeme function
mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

Values inside the function: [10, 20, 30, [1, 2, 3, 4]] Values outside the function: [10, 20, 30, [1, 2, 3, 4]]

def changeme( mylist ):
    "This changes a passed list into this function"
   mylist = [1,2,3,4]; # This would assig new reference in mylist
   print "Values inside the function: ", mylist
   return

# Now you can call changeme function
mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

Values inside the function: [1, 2, 3, 4] Values outside the function: [10, 20, 30]

calcMan
  • 111
  • 1
  • 12

2 Answers2

2

This is one of the most important things you will learn about Python (well, it was for me).

Every object is inherently unnamed but you can bind a variable name to it.

When you do:

x = [1, 2, 3]

two things happen:

  • the [1, 2, 3] object is created; and
  • the x name is bound to it.

That's why, when you change an object, all bound names seem to change(1):

>>> x = [1, 2, 3] ; y = x ; x ; y
[1, 2, 3]
[1, 2, 3]
>>> x.append(42) ; x ; y
[1, 2, 3, 42]
[1, 2, 3, 42]

You're not changing x or y in that case, you're changing the object behind those variables and, since both variables are bound to that object, both will be affected.

So, how does that affect your question. When you pass a variable to a function, the name in the function definition is simply bound to the same object as the one you passed in:

def modList(x):      # 'x' and 'actual' now point to the SAME object.
    x.append(42)     # this will modify that object, no binding changes.
    x = [4, 5, 6]    # this will create NEW object and rebind 'x' to it.

actual = [1, 2, 3]   # object is [1, 2, 3], 'actual' is bound to it.
modList(actual)      # pass object reference to function.

So statements that change the object (like the first line of modList) will change it for all bindings whereas statements that rebind (like the second line) will lose access to the original object.

If you want to change the object with an assignment-looking statement, you can use array slicing to do so. This works because you're changing the elements in the object rather than rebinding x to a new object:

x[:] = [4, 5, 6]

(1) Note that you can't always change the object behind a binding. Specifically, some things (like strings) are immutable so, if you "change" a string, you actually get a new string, distinct from the first:

x = "pax"         # New object, bind x to it.
y = x             # Bind y to that same object.
x = x + "diablo"  # New object, bind x to it. Bindings x and y
                  #   do not affect each other, they are bound
                  #   to different objects.
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

mylist = [1,2,3,4] in the function changes the value of the parameter mylist, which is a copy of the reference to mylist outside of the function. The original reference does not change.

If you want to modify the list (rather than a reference to it), use mylist[:] = [1,2,3,4].

DYZ
  • 55,249
  • 10
  • 64
  • 93