Your function does not give consistent answers on how to sort numbers, because
greater(x, y) != not greater(y, x) for some values of x and y. For example
(3 % 4) % 2 == 1, and
(4 % 3) % 2 == 1 also! This means that
3 > 4 AND
3 < 4, which is nonsense. If you convert it to a cmp-style function like @SystemDown suggests, you will get inconsistent results. For example:
>>> sorted(range(3, 6), cmp=greater)
[5, 4, 3]
>>> sorted(range(1, 6), cmp=greater)
[1, 4, 3, 5, 2]
Here 5 is smaller than 4 in one case but larger than 4 in another, using the same comparison function!
Even if your cmp function was self-consistent, I'd advice against using it in any way or form, like using the
cmp_to_key function suggested by @zstewart, because a cmp function is slower harder to read and debug than an equivalent key function.
Using key functions, the function gets called only once per item to be sorted, so if you have a list of 1 million items, it gets called a million times. Then the sorting proceeds and compares the return values of the key function
n*log(n) times, on average. For a list of 1 million elements, that's 13.8 million times.
If you use a cmp function instead, it gets called once for each of those
n*log(n) comparisons! Again, that's 13.8 million times if the list contains 1 million elements. If you use
cmp_to_key, you'll get an additional overhead of instantiating 1 million instances of a helper class.
I tested with a list of 1 million random integers using these functions, which accomplish the same thing:
def cmp_func(a, b):
if a > b:
elif a < b:
key_func took 1.35 s, while using
cmp_func required 2.43 s.
So to answer the implicit question of @lzkata, it was deemed a good idea to remove the cmp argument to sort in 3.x because
- cmp functions are prone to produce inconsistent results in subtle ways, resulting in subtle and hard-to-find bugs
- cmp functions are slower
- it's almost always possible to convert a cmp function to a better performing key function