В Python, как list.sort
метод и sorted
встроенная функция принимает необязательный параметр с именем key
, который является функцией, которая, учитывая элемент из списка возвращает его сортировки ключ.
В старых версиях Python использовался другой подход, в котором вместо этого использовался параметр cmp
, который представляет собой функцию, которая, учитывая, что два элемента из списка возвращают отрицательное число, если первое меньше второго, и ноль, если есть равные, и положительное число, если первое лучше. В какой-то момент этот параметр устарел и не был включен в Python 3.
На днях я хотел отсортировать список элементов таким образом, чтобы функция cmp
была гораздо проще написать, чем key
. Я не хотел использовать устаревшую функцию, так что я прочитал документацию, и я обнаружил, что есть Funtion имени cmp_to_key
в functools
модуле, который, как и его название состояния, получает cmp
функцию и возвращает key
один... или что что я думал, пока не прочитал исходный код (или хотя бы эквивалентную версию) этой функции высокого уровня, включенной в документы
def cmp_to_key(mycmp):
'Convert a cmp= function into a key= function'
class K(object):
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
Несмотря на то, что cmp_to_key
работает, как и ожидалось, меня удивляет тот факт, что эта функция возвращает не функцию, а класс K
Зачем? Как это работает? Я предполагаю, что sorted
функция внутренне проверяет, является ли cmp функцией, или классом K, или чем-то подобным, но я не уверен.
PS: Несмотря на эту странность, я обнаружил, что класс K очень полезен. Проверьте этот код:
from functools import cmp_to_key
def my_cmp(a, b):
# some sorting comparison which is hard to express using a key function
class MyClass(cmp_to_key(my_cmp)):
...
Таким образом, любой список экземпляров MyClass может быть по умолчанию отсортирован по критериям, определенным в my_cmp