Another topic that is surprisingly close to mutations is sorting. That relation comes because usually you need to sort a list. Sorting a list is extremely easy in python, as easy as using list.sort() method. And as confusing as everything we've discussed so far...
In [ ]:
a = [2, 6, 3, 4, 1, 9]
print ("List before sorting", a)
b = a.sort()
print ("That's what list.sort() returns:", b)
print ("List after sorting", a)
Two things you may noticed:
That happens because sort() method performs sorting as a side effect, and it does not create a new list of sorted objects. As you might know by now, if you have an alias for a, it's get sorted (unlike a copy) after any of them calls sort() method.
In [ ]:
a = [2, 6, 3, 4, 1, 9]
a_copy = a[:]
a_alias = a
print ("List before sorting", a)
print ("List alias before sorting", a_alias)
print ("List copy before sorting", a_copy)
print ("------------------------------------------")
a_copy.sort()
print ("List after sorting copy", a)
print ("List alias after sorting copy", a_alias)
print ("List copy after sorting copy", a_copy)
In [ ]:
a = [2, 6, 3, 4, 1, 9]
a_copy = a[:]
a_alias = a
a.sort()
print ("List after sorting", a)
print ("List alias after sorting", a_alias)
print ("List copy after sorting", a_copy)
In [ ]:
a = [2, 6, 3, 4, 1, 9]
a_copy = a[:]
a_alias = a
a_alias.sort()
print ("List after sorting alias", a)
print ("List alias after sorting alias", a_alias)
print ("List copy after sorting alias", a_copy)
But that's not the only way of sorting stuff in python. There is a built-in function, sorted(), that among other things can sort lists. In a slightly different manner:
In [ ]:
a = [2, 6, 3, 4, 1, 9]
print ("List before sorting", a)
b = sorted(a)
print ("That's what 'sorted(list)' returns:", b)
print ("List after sorting", a)
As you can see, sorted() not only sorts the list, it returns a new list where the elements are already sorted. On the other hand, sorted() does not change the state of original list. So here is a good rule of thumb: if you need to sort a list forever and you don't care about its previous state, use list.sort(). If you need a new list with sorted elements, use sorted().
Sorted is a very powerful function, that can sort virtually anything, if it's iterable and comparable (or in simple English, if it can be sorted). Among those thing, you can sort tuples, because by using sorted() you don't change it. But as a result you're going to see a list:
In [ ]:
a = (2, 6, 3, 4, 1, 9)
print ("Tuple before sorting", a)
b = sorted(a)
print ("That's what 'sorted(tuple)' returns:", b)
print ("Tuple after sorting", a)
More than that, you can pass a special function (key, or comparator) to specify how exactly you need you collection to be sorted, and even sort in the reverse order. For example, let's sort a tuple of pairs in reverse order be the second element of the pair, and then by the first:
In [ ]:
from operator import *
a = ((2, 1), (6, 2), (3, 3), (4, 4), (1, 5), (9, 6))
b = sorted(a, key=itemgetter(1), reverse=True)
c = sorted(a, key=itemgetter(0), reverse=True)
print ("Tuple before sorting", a)
print ("Tuple after sorting by the second element of pair", b)
print ("Tuple before sorting by the first element of pair", c)
In [ ]:
from collections import defaultdict
a = "how many characters are in this sentence, and which one is the most common one?"
def find_most_common_character(s):
chars = defaultdict(int)
words = s.split(" ")
for word in words:
for c in word:
chars[c] += 1
# Q: How about sorting dictionary by key?
return sorted(chars.items(), key=lambda item: item[1], reverse=True)[0]
find_most_common_character(a)
You can run even more complex sort operations, like sorting dictionaries be the value and so on. If you are more interested in how sort things out in python, you can read more about that on the corresponding documentation page