This lab integrates several topics we have talked about over the last few weeks. It can sometimes be difficult to remember just which class is relevant…
As we have seen in many contexts, the Python built-in functions are designed to
be highly flexible, but with sane defaults. Often the defaults are all we need,
but sometimes not. In this lab you might find yourself needing to change the
behavior of several functions. First consider sorted
:
>>> help(sorted)
Help on built-in function sorted in module builtins:
sorted(iterable, key=None, reverse=False)
Return a new list containing all items from the iterable in ascending order.
A custom key function can be supplied to customise the sort order, and the
reverse flag can be set to request the result in descending order.
The default behavior of sorted
is to compare items in the iterable collection
(and sort them in ascending order). But if what if our items are complex
objects and we only want to order them based on a specific component or
subfield (or otherwise change the “default” ordering)? The optional key
function allows us
to control the sorting behavior by customizing the key used in the comparison.
In one of our problem sets we worked with the following dictionary of particles and their probability of detection. How could we order the particles in increasing order of probability?
>>> d = {'neutron': 0.55, 'proton': 0.21, 'meson': 0.03, 'muon': 0.07, 'neutrino': 0.14}
>>> sorted(d.items())
[('meson', 0.03), ('muon', 0.07), ('neutrino', 0.14), ('neutron', 0.55), ('proton', 0.21)]
Sorting the items with the default behavior directly compares the key-value
tuples, which compares the first elements of the tuples and then the
second. How can we use the key
function to just compare the tuples by the
second element, the probability? We need to write and supply a key function
that has the tuple as a parameter and returns the second element as the key to
be used in sorting.
>>> def get_2nd(item):
... return item[1]
...
>>> sorted(d.items(), key=get_2nd)
[('meson', 0.03), ('muon', 0.07), ('neutrino', 0.14), ('proton', 0.21), ('neutron', 0.55)]
Notice the items are now sorted in the desired way. In Python
functions are objects too and be used as arguments. We are not invoking
get_2nd
we supplying it as an argument to sorted
to be called by sorted
as it executes.
What if we wanted to sort the items in descending order of probability? Note
the reverse
optional argument in the sorted
documentation that “can be set
to request the result in descending order”. For example:
>>> sorted(d.items(), key=get_2nd, reverse=True)
[('neutron', 0.55), ('proton', 0.21), ('neutrino', 0.14), ('muon', 0.07), ('meson', 0.03)]
In general, needing to control the sort order (both what is compared and whether items are sorted in ascending or descending order) is so common that we should assume every language as a way to change these behaviors. The details may be different, but the functionality will be there. As we gain experience will learn what to expect of our programming languages.