Python max przy użyciu „klucza” i wyrażenia lambda

181

Pochodzę z OOP i próbuję nauczyć się Pythona. Używam maxfunkcji, która używa wyrażenia lambda, aby zwrócić wystąpienie typu, Playerktóre ma maksimum totalScorena liście players.

def winner():
    w = max(players, key=lambda p: p.totalScore)

Funkcja poprawnie zwraca instancję typu Playermającą maksimum totalScore. Jestem zdezorientowany co do następujących trzech rzeczy:

  1. Jak działa ta maxfunkcja? Jakie argumenty podejmuje? Przejrzałem dokumentację, ale nie zrozumiałem.
  2. Jakie jest zastosowanie słowa kluczowego keyw funkcji max? Wiem, że jest również używany w kontekście sortfunkcji
  3. Znaczenie wyrażenia lambda? Jak je czytać? Jak oni pracują?

Są to bardzo niedorzeczne konceptualne pytania, ale pomogą mi zrozumieć język. Byłoby pomocne, gdybyś mógł podać przykłady wyjaśniające. Dzięki

Vijay
źródło
Która wersja Pythona?
charmlessCoin
2
Czy zapoznałeś się z dokumentacją ?
Inbar Rose
@charmlessCoin python 2.7.5
Vijay
2
@InbarRose Sprawdziłem w dokumentacji funkcję max. Naprawdę tego nie rozumiałem.
Vijay
10
@InbarRose Ta strona jest obecnie najlepszym wynikiem w Google python max lambdadla nowych użytkowników i może być bardziej pomocna.
Mark

Odpowiedzi:

278

lambda jest funkcją anonimową, jest odpowiednikiem:

def func(p):
   return p.totalScore     

Teraz maxstaje się:

max(players, key=func)

Ponieważ jednak definstrukcje są instrukcjami złożonymi, nie można ich używać tam, gdzie wymagane jest wyrażenie, dlatego czasami lambdasą używane.

Zauważ, że lambdajest to równoważne temu, co umieściłeś w instrukcji zwrotu pliku def. Dlatego nie możesz używać instrukcji wewnątrz a lambda, dozwolone są tylko wyrażenia.


Co robi max?

max (a, b, c, ... [, klucz = func]) -> wartość

Za pomocą pojedynczego iterowalnego argumentu zwróć jego największy element. W przypadku dwóch lub więcej argumentów zwraca największy argument.

Więc po prostu zwraca obiekt, który jest największy.


Jak to keydziała?

Domyślnie w Pythonie 2 keyporównuje elementy w oparciu o zestaw reguł opartych na typie obiektów (na przykład łańcuch jest zawsze większy niż liczba całkowita).

Aby zmodyfikować obiekt przed porównaniem lub porównać na podstawie określonego atrybutu / indeksu, musisz użyć keyargumentu.

Przykład 1:

Prosty przykład: załóżmy, że masz listę liczb w postaci ciągu, ale chcesz porównać te elementy według ich wartości całkowitych.

>>> lis = ['1', '100', '111', '2']

Tutaj maxporównuje elementy przy użyciu ich oryginalnych wartości (łańcuchy są porównywane leksykograficznie, aby uzyskać '2'wynik):

>>> max(lis)
'2'

Aby porównać elementy według ich wartości całkowitej, użyj keyprostego lambda:

>>> max(lis, key=lambda x:int(x))  # compare `int` version of each item
'111'

Przykład 2: zastosowanie maxdo listy krotek.

>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]

Domyślnie maxporównuje elementy według pierwszego indeksu. Jeśli pierwszy indeks jest taki sam, porówna drugi indeks. Tak jak w moim przykładzie, wszystkie elementy mają unikalny pierwszy indeks, więc otrzymasz odpowiedź:

>>> max(lis)
(4, 'e')

Ale co by było, gdybyś chciał porównać każdą pozycję według wartości pod indeksem 1? Proste: użycie lambda:

>>> max(lis, key = lambda x: x[1])
(-1, 'z')

Porównanie elementów w iterowalnej, która zawiera obiekty różnego typu :

Lista z elementami mieszanymi:

lis = ['1','100','111','2', 2, 2.57]

W Pythonie 2 możliwe jest porównanie elementów dwóch różnych typów :

>>> max(lis)  # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # compare integer version of each item
'111'

Ale w Pythonie 3 nie możesz już tego robić :

>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
  File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    max(lis)
TypeError: unorderable types: int() > str()

Ale to działa, ponieważ porównujemy wersję całkowitą każdego obiektu:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'
Ashwini Chaudhary
źródło
Myślę, że to jest stare, ale mam w związku z tym pytanie. Widzę, że w przypadku funkcji lambda zmienna x lub i lub cokolwiek innego zawsze reprezentuje wartość w tym indeksie na liście. Czy ta iteracja jest wykonywana przez funkcję max czy przez lambdę? Czy funkcje lambda zawsze iterują po możliwych wartościach? Na przykład: lengths = map(lambda word: len(word), words)gdzie words=['It', 'is', 'raining', 'cats', 'and', 'dogs']widzę, że lambda iteruje po każdym słowie na liście. Czy zawsze to robi?
Pn. 2
1
@ Mo2 Iteracja jest wykonywana przez maxnot lambda( keyargument jest opcjonalny), a podczas iteracji każdy element jest przekazywany do funkcji określonej w, keya zwracana wartość jest następnie używana do porównania.
Ashwini Chaudhary
2
Tylko dla osób, które przyszły tutaj, wpisując w Google „maksymalny parametr klucza”. max(lis, key=lambda x:int(x))można uprościć jako max(lis, key=int). Python ma wbudowaną funkcję int (). Podobnie możesz użyć dowolnych innych funkcji wbudowanych jako keyargumentu. Na przykład można uzyskać najdłuższy łańcuch z lis=['a', 'aa', 'aaa']przezmax(lis, key=len)
YOUNG
1
@YOUNG Możemy użyć dowolnej funkcji jako kluczowego argumentu nie tylko wbudowanej funkcji, jedynym warunkiem jest to, że funkcja powinna przyjąć elementy przekazywane do niej przez max, min, sortedetc prawidłowo. Poza tym wspomniałem max(lis, key=int)na końcu. :-)
Ashwini Chaudhary
@Ashwini Chaudhary .. przypuśćmy, że jeśli mam listę taką jak [1,2,3,4,5]. tutaj wszystkie elementy są różne. Używam podanej funkcji max (set (mylist), key = mylist.count), aby znaleźć najczęstsze pozycje. ponieważ w tym przypadku nie ma elementu, który się powtarza. zwraca najniższą pozycję. Czy możemy coś zrobić, aby w takim przypadku zwracało zero lub zero.
vikrant rana
12

Mocno uproszczona wersja max:

def max(items, key=lambda x: x):
    current = item[0]
    for item in items:
        if key(item) > key(current):
            current = item
    return current

Odnośnie lambda:

>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5

>>> times_two = lambda x: 2*x
>>> times_two(2)
4
Markus Unterwaditzer
źródło
10

Jak działa funkcja max?

Szuka „największego” elementu w iterowalnej. Zakładam, że możesz sprawdzić, co to jest, ale jeśli nie, jest to coś, co możesz zapętlić, np. Lista lub łańcuch.

Jakie jest zastosowanie klucza słowa kluczowego w funkcji max? Wiem, że jest również używany w kontekście funkcji sortowania

Keyto funkcja lambda, która powie, maxktóre obiekty w iterowalnej są większe niż inne. Powiedz, czy sortujesz obiekt, który sam stworzyłeś, a nie coś oczywistego, na przykład liczby całkowite.

Znaczenie wyrażenia lambda? Jak je czytać? Jak oni pracują?

To trochę większe pytanie. Mówiąc najprościej, lambda to funkcja, którą można przekazywać i używać jej w innych fragmentach kodu. Weź to na przykład:

def sum(a, b, f):
    return (f(a) + f(b))

To wymaga dwóch obiektów ai b, i funkcji f. Wzywa f()każdy obiekt, a następnie dodaje je do siebie. Więc spójrz na to wezwanie:

>>> sum(2, 2, lambda a:  a * 2)
8

sum()przyjmuje 2i wywołuje wyrażenie lambda. f(a)Staje się więc 2 * 2, co staje się 4. Następnie robi to za bi dodaje je do siebie.

Mówiąc nie tak prosto, lambdy pochodzą z rachunku lambda, który jest ideą funkcji, która zwraca funkcję; bardzo fajna koncepcja matematyczna do wyrażania obliczeń. Możesz o tym poczytać tutaj , a potem faktycznie to zrozumieć tutaj .

Prawdopodobnie lepiej jest o tym poczytać trochę więcej, ponieważ lambdy mogą być mylące i nie jest od razu oczywiste, jak są przydatne. Sprawdź tutaj .

charmlessCoin
źródło
7

max funkcja służy do uzyskania maksimum z pliku iterable .

Iteratorami mogą być listy, krotki, obiekty dyktowania itp. Lub nawet obiekty niestandardowe, jak w podanym przykładzie.

max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.

Tak więc w key=funczasadzie pozwala nam przekazać opcjonalny argumentkey do funkcji, na podstawie której sortowany jest dany iterator / argumenty i zwracane jest maksimum.

lambdajest słowem kluczowym Pythona, które działa jak pseudo funkcja. Tak więc, kiedy przekażesz mu playerobiekt, zwróci player.totalScore. Zatem iterable przeszło do funkcji maxbędzie sortowania według key Całkowity wynik z playerprzedmiotów podanych do niego i zwróci playerktóry ma maksimum totalScore.

Jeśli nie keypodano argumentu, zwracana jest wartość maksymalna zgodnie z domyślną kolejnością Pythona.

Przykłady -

max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7

people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')
shad0w_wa1k3r
źródło
6

Zgodnie z dokumentacją :

max (iterowalne [, klucz])
max (arg1, arg2, * args [, klucz])
Zwraca największy element w iterowalnej lub największy z dwóch lub więcej argumentów.

Jeśli podano jeden argument pozycyjny, iterowalność musi być niepustą iterowalną (taką jak niepusty ciąg, krotka lub lista). Zwracany jest największy element w iterowalnej. Jeśli podano dwa lub więcej argumentów pozycyjnych, zwracany jest największy z argumentów pozycyjnych.

Opcjonalny argument klucz określa jednoargumentową funkcję porządkującą, taką jak używana w przypadku list.sort (). Argument klucza, jeśli został podany, musi mieć postać słowa kluczowego (na przykład max (a, b, c, klucz = func)).

To mówi, że w twoim przypadku dostarczasz listę, w tym przypadku players. A późniejmax funkcja dokona iteracji po wszystkich elementach na liście i porówna je ze sobą, aby uzyskać „maksimum”.

Jak możesz sobie wyobrazić, w przypadku złożonego obiektu, takiego jak playerokreślenie jego wartości do porównania, jest trudne, więc masz keyargument do określenia, w jaki sposób maxfunkcja zdecyduje o wartości każdego z nich player. W tym przypadku używasz funkcji lambda, aby powiedzieć „for each pin playersget p.totalscorei użyj tego jako jego wartości do porównania”.

Inbar Rose
źródło
3

max jest wbudowaną funkcją, która przyjmuje pierwszy argument an iterable (jak lista lub krotka)

Argument słowo kluczowe keyma swoją wartość domyślną, Noneale akceptuje funkcję do oceny, traktuje ją jako opakowanie, które ocenia iterowalność na podstawie funkcji

Rozważmy ten przykładowy słownik:

d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}

Dawny:

>>> max(d.keys())
'sword'

Jak widać, jeśli przekażesz tylko iterowalną bez kwarg (funkcję do key), zwraca maksymalną wartość klucza (alfabetycznie)

Dawny. Zamiast znajdować maksymalną wartość klucza alfabetycznie, może być konieczne znalezienie maksymalnego klucza według długości klucza:

>>>max(d.keys(), key=lambda x: len(x))
'artwork'

w tym przykładzie funkcja lambda zwraca długość klucza, który będzie iterowany, dlatego podczas obliczania wartości zamiast rozważać alfabetycznie będzie śledzić maksymalną długość klucza i zwróci klucz, który ma maksymalną długość

Dawny.

>>> max(d.keys(), key=lambda x: d[x])
'friend'

w tym przykładzie funkcja lambda zwraca wartość odpowiedniego klucza słownika, który ma maksymalną wartość

Gahan
źródło