2013-05-03 7 views
28

Natknąłem się na tę funkcję here.Jak działa funkcja cmp_to_key w Pythonie?

jestem zaskoczony, w jaki sposób miałoby to być realizowane - w jaki sposób funkcja key generowane przez cmp_to_key wiedzieć co „pozycja” dany element powinien być bez sprawdzenia, w jaki sposób dany element porównuje z każdym innym elementem zainteresowania?

Odpowiedz

35

Sposób cmp_to_key zwraca szczególną obiekt, który działa jako klucz zastępczy:

class K(object): 
    __slots__ = ['obj'] 
    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 
    def __hash__(self): 
     raise TypeError('hash not implemented') 

Przy sortowaniu, każdy klucz dostanie w porównaniu do większości innych klawiszy w sekwencji. Czy ten element w pozycji 0 jest niższy lub większy niż ten inny obiekt?

Kiedy to nastąpi, wywoływane są specjalne haki metod, więc wywoływana jest __lt__ lub __gt__, a klucz zastępczy zamienia się w wywołanie metody cmp.

więc lista jest sortowana [1, 2, 3] jak [K(1), K(2), K(3)], a jeśli, powiedzmy, K(1) jest porównywana z K(2) aby zobaczyć czy K(1) jest niższa, a następnie K(1).__lt__(K(2)) nazywa, które są tłumaczone na mycmp(1, 2) < 0.

W ten sposób stara metoda cmp działała w każdym razie ; return -1, 0 lub 1 w zależności od tego, kto pierwszy argument jest niższy, równy lub większy niż drugi argument. Klucz zastępczy przekształca te liczby z powrotem na wartości logiczne dla operatorów porównania.

W żadnym punkcie zastępczy klucz nie musi nic wiedzieć o pozycjach bezwzględnych. Musi tylko wiedzieć o innym obiekcie, z którym jest porównywany, a specjalne haki metody zapewniają ten inny obiekt.

+0

Wow, rzeczywistą instancją było to, że Java ma znacznie prostsze rozwiązanie tego samego problemu niż Python. Nie ma ich wiele. – jeremyjjbrown

+2

@jeremyjjbrown: funkcja 'cmp_to_key' istnieje tylko w celu obsługi starszych algorytmów sortowania. Prostsza metoda pythonic polega na użyciu funkcji 'key' zamiast' sorted() '. –

+0

Czasami bardzo trudno wymyślić 'klucz', ale łatwo wymyślić funkcję porównania ... np. Chcę posortować listę liczb tak, aby wszystkie liczby nieparzyste były pierwsze, w porządku rosnącym, a następnie wszystkie liczby parzyste są następne, w malejącej kolejności. – rlbond