1

I have this piece of code in Python:

def sortList(x):
   x.sort()
   print "Values inside the function: ", x
   return

mylist = [100,20,30];
sortList(mylist);
print "Values outside the function: ", mylist

The output is:

Values inside the function:  [20, 30, 100]
Values outside the function:  [20, 30, 100]

Now, instead of writing x.sort() if I write x=[1,2,3] then the output is:

Values inside the function:  [1, 2, 3]
Values outside the function:  [100, 20, 20]

So why does the value of the array "mylist" change from inside the function? And that too only when I perform some operation on it, and not when I assign completely new value to it?

Thanks!

Shod
  • 801
  • 3
  • 12
  • 33
  • It's worth looking at this which is related: http://stackoverflow.com/questions/12797749/python-and-reference-passing-limitation?rq=1 – EdChum Feb 18 '15 at 13:43
  • Because `list.sort` is **in-place**, modifying the object and returning `None`, whereas `x = [1, 2, 3]` assigns the name `x` to a **completely new object**, and doesn't affect `mylist` at all. – jonrsharpe Feb 18 '15 at 13:44

3 Answers3

1

Because arguments are passed by assignment, argument names in the function may share objects with variables in the scope of the call. Hence, in-place changes to mutable arguments in a function can impact the caller.

And in your code at first time because of you use sort() function and it change the x in-place, it impact the caller and change the x globally!But when you assign a new object to x actually you create a local variable inside the function that references to your new object ([1, 2, 3]).

So for avoiding Mutable Argument Changes you can pass a copy of your variable to function :

mylist = [100,20,30];
sortList(mylist[:]);
print "Values outside the function: ", mylist

result :

Values inside the function:  [20, 30, 100]
Values outside the function:  [100, 20, 30]

As another way you can convert your argument to an immutable object that changes on it will raise an error, in this case you can convert your list to tuple:

mylist = [100,20,30];
sortList(tuple(mylist));
print "Values outside the function: ", mylist

Traceback (most recent call last):
  File "/home/bluebird/Desktop/try.py", line 7, in <module>
    sortList(tuple(mylist));
  File "/home/bluebird/Desktop/try.py", line 2, in sortList
    x.sort()
AttributeError: 'tuple' object has no attribute 'sort'
Mazdak
  • 105,000
  • 18
  • 159
  • 188
1

You're passing an object value into your function, then you're modifying that object. This changes the object. There's only ever one object, Python does not create an independent copy of the object when you pass it into the function.

Now, if you assign an entirely different object to the variable x, that doesn't do anything to the object which was previously in x. It merely breaks the reference from x to that object. Since that object is still referenced by mylist, it continues to exist just fine.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • I understand what you said in the first para.. But, shouldn't the same logic be applied to, when you are assigning? I mean, even an "assignment" is kind of "modifying the object" right? Please let me know if I am going wrong somewhere.. – Shod Feb 18 '15 at 14:07
  • Variables are "placeholders" in an algorithm. They hold values. A variable *is* not the value. `=` puts a value into a variable, it does not modify the value that may have been in it before. – deceze Feb 18 '15 at 22:29
0

It's simple: python passes argument not by value (meaning a copy), but instead by reference. Thus inside sortList, you manipulate the very same list you pass in. It's up to the discretion of the developer to remedy this. One way would be to use the sorted call instead, which gives you a sorted copy of a sequence. Others involve the use of copy.copy or copy.deepcopy

deets
  • 6,285
  • 29
  • 28