Can anyone explain why .sort() is working this way?

Very curious as to why .sort is working in a particularized way. Here’s what I’m coding:

def median(input_list):
  print input_list
  output_list = input_list
  output_list.sort()
  print output_list
  print input_list

I cannot explain why but when I print input_list in this scenario, it is suddenly sorted, even though I only told the code to sort output_list. I realize that I have output_list set to be input_list, but so far that’s not how variables or lists have worked. The first time input_list prints, it is in the intended unsorted format. But once output_list gets .sort(), suddenly printing input_list a second time now prints a sorted input_list.

I can get the following to work:

def median(input_list):
  print input_list
  output_list = sorted(input_list)
  print output_list
  print input_list

But (1) I haven’t formally been taught sorted at this point in Codecademy and (2) I just fundamentally don’t understand why .sort() isn’t working.

Any help would be greatly appreciated! Thanks.

This seems to be the best answer I’ve found on the internet:

The main difference between sort() and sorted() is that the sorted() function takes any iterable (list, tuple, set, dictionary) and returns a new sorted object without affecting the original. On the other hand, sort() does in-place sorting meaning it won’t create a new list but updates the given list itself in the desired order (ascending or descending).

Very strange behavior in my opinion. Essentially, the answer to my question is “Because that’s just something that the .sort function does – it affects the original no matter what.” Something that you’d only know after encountering it like this. Which still seems weird because I never told it to sort input_list. I created an entire duplicate list, set it equal to input_list, and .sort still reached all the way back to sort the original list I never gave it permission to touch. Am I misunderstanding this? Please let me know if I am.

It does make sense now why Codecademy did not request to me leave the original list unchanged now. This was on exercise 15 of 15 in practice makes perfect. The question immediately before this made it a condition of the problem that you not modify the original list and made a point that modifying original lists is bad practice, so I tried my damnedest to not modify the original list in this exercise.

In Python, objects can be mutable or immutable.
Numbers, strings, tuples are immutable objects.

my_string = "abcd"
my_string[1] = "e" // Error
my_string = my_string[0] + "e" + my_string[2:] // Creates a new string
                                              // and assigns to variable
my_string = "aecd" // Doesn't modify string "abcd". Instead new string is created.

my_tuple = (1, 5, 3)
my_tuple[1] = 2 // Error. Tuples are immutable.
my_tuple = (1, 2, 3) // New tuple created 

Contrast this with mutable objects.
Lists, Dictionaries and Sets are mutable objects. You can modify the original object without a new object being created from scratch.

my_list = [1, 5, 3]
my_list[1] = 2 // Original list modified
print(my_list) // [1, 2, 3]

VARIABLES

Immutable Example
a = "hello"
b = a
b = "hey"
print(a)  // "hello"
print(b)  // "hey"
// b = a  does not create a copy of the string. 
// (You can verify this by comparing id(a) and id(b))
// Both variables point to the same string in memory.
// b = "hey" Now, b points to a different string, 
// while a still points to original string.

Mutable Example
a = [1, 2, 3, 4, 5]
b = a
b[2] = 77
print(a) // [1, 2, 77, 4, 5]
print(b) // [1, 2, 77, 4, 5]
// b = a does not create a copy of the list.
// The same object (the same list) is being referenced 
// by the two variables a and b.
// Mutating the object will affect both a and b.

An easy way of copying a list is

a = [1, 2, 3, 4, 5]
b = a[:]
b[2] = 77
print(a) // [1, 2, 3, 4, 5] 
print(b) // [1, 2, 77, 4, 5]

However [:] will only create a shallow copy of the list. If there are lists nested in the original list, then shallow copy won’t suffice. Instead, deep copy can be used.

Further reading,
https://docs.python.org/3/library/copy.html

1 Like

Thank you so much for such a thorough answer. I greatly appreciate it. I feel like I’m going to be referencing your answer a few times over the next few weeks, so thanks again – this helps a lot.

1 Like