In Python, sia il metodo list.sort
che la funzione integrata sorted
accettano un parametro opzionale denominato key
, che è una funzione che, dato un elemento dall'elenco restituisce la sua chiave di ordinamento.Python: come funziona la funzione cmp_to_key di functools?
Le versioni precedenti di Python utilizzavano un approccio diverso utilizzando invece il parametro cmp
, che è una funzione che, dati due elementi dall'elenco restituisce un numero negativo se il primo è inferiore al secondo, zero se ci sono uguali e positivo numero se il primo è maggiore. Ad un certo punto, questo parametro era deprecato e non era incluso in Python 3.
L'altro giorno volevo ordinare un elenco di elementi in modo che una funzione cmp
fosse molto più semplice da scrivere rispetto a uno key
. Non volevo utilizzare una funzionalità deprecata, quindi ho letto la documentazione e ho scoperto che esiste una funzione denominata cmp_to_key
nel modulo functools
che, come afferma il suo nome, riceve una funzione cmp
e restituisce uno key
... o quello è quello che ho pensato fino a quando ho letto il codice sorgente (o almeno una versione equivalente) di questa funzione di alto livello incluso nel docs
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
Nonostante il fatto che cmp_to_key
opere come previsto, ottengo sorpreso dal fatto che questo la funtion non restituisce una funzione, ma una classe K
. Perché? Come funziona? Suppongo che la funzione sorted
controlli internamente se cmp è una funzione o una classe K o qualcosa di simile, ma non ne sono sicuro.
P.S .: Nonostante la sua unicità, ho trovato che la classe K è molto utile. Controllare questo codice:
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)):
...
In questo modo, qualsiasi elenco di istanze di MyClass può essere, per impostazione predefinita, ordinato secondo i criteri definiti nel my_cmp
Grande spiegazione. – abc