272 votes

Fonction python max utilisant 'key' et l'expression lambda

Je viens d'un background OOP et j'essaie d'apprendre Python. Je suis en train d'utiliser la fonction max qui utilise une expression lambda pour retourner l'instance de type Player ayant le totalScore maximum parmi la liste players.

def gagnant():
    g = max(players, key=lambda p: p.totalScore)

La fonction retourne correctement l'instance de type Player ayant le totalScore maximum. Je suis confus concernant les trois points suivants :

  1. Comment fonctionne la fonction max ? Quels sont les arguments qu'elle prend ? J'ai regardé la documentation mais je n'ai pas compris.
  2. Quel est l'usage du mot-clé key dans la fonction max ? Je sais qu'il est également utilisé dans le contexte de la fonction sort.
  3. Signification de l'expression lambda ? Comment les lire ? Comment fonctionnent-elles ?

Ce sont toutes des questions conceptuelles très basiques mais qui m'aideront à comprendre le langage. Ce serait utile si vous pouviez donner des exemples pour expliquer. Merci

410voto

Ashwini Chaudhary Points 94431

lambda est une fonction anonyme, équivalente à :

def func(p):
   return p.totalScore     

Maintenant max devient :

max(players, key=func)

Cependant, comme les instructions def sont des instructions composées qui ne peuvent pas être utilisées là où une expression est requise, c'est pourquoi parfois on utilise des lambda.

Remarquez que lambda est équivalent à ce que vous mettriez dans une instruction return d'une def. Ainsi, vous ne pouvez pas utiliser d'instructions à l'intérieur d'un lambda, seules des expressions sont autorisées.


Que fait max ?

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

Avec un seul argument itérable, retourne son élément le plus grand. Avec deux arguments ou plus, retourne le plus grand argument.

Ainsi, il retourne simplement l'objet qui est le plus grand.


Comment fonctionne key ?

Par défaut en Python 2, key compare les éléments en fonction d'un ensemble de règles basées sur le type des objets (par exemple, une chaîne est toujours plus grande qu'un entier).

Pour modifier l'objet avant la comparaison, ou pour comparer en fonction d'un attribut/index particulier, vous devez utiliser l'argument key.

Exemple 1 :

Un exemple simple, supposons que vous ayez une liste de nombres sous forme de chaîne, mais que vous vouliez comparer ces éléments par leur valeur entière.

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

Ici, max compare les éléments en utilisant leurs valeurs d'origine (les chaînes sont comparées lexicographiquement donc vous obtiendriez '2' en sortie) :

>>> max(lis)
'2'

Pour comparer les éléments par leur valeur entière, utilisez key avec un simple lambda:

>>> max(lis, key=lambda x:int(x))  # comparer la version `int` de chaque élément
'111'

Exemple 2 : Application de max à une liste de tuples.

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

Par défaut, max comparera les éléments par le premier indice. Si le premier indice est le même, il comparera le deuxième indice. Dans mon exemple, tous les éléments ont un premier indice unique, donc vous obtiendriez ceci comme réponse :

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

Mais, que faire si vous vouliez comparer chaque élément par la valeur à l'index 1 ? Simple : utilisez lambda :

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

Comparaison des éléments dans un itérable contenant des objets de types différents :

Liste avec des éléments mixtes :

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

En Python 2, il est possible de comparer des éléments de types différents :

>>> max(lis)  # fonctionne en Python 2
'2'
>>> max(lis, key=lambda x: int(x))  # comparer la version entière de chaque élément
'111'

Mais en Python 3, ce n'est plus possible :

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

Mais cela fonctionne, car nous comparons la version entière de chaque objet :

>>> max(lis, key=lambda x: int(x))  # ou simplement `max(lis, key=int)`
'111'

24voto

Version fortement simplifiée de max:

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

Concernant lambda:

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

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

14voto

Ashish Nitin Patil Points 2054

La fonction max est utilisée pour obtenir le maximum d'un itérable.

Les itérateurs peuvent être des listes, des tuples, des objets dict, etc. Ou même des objets personnalisés comme dans l'exemple que vous avez fourni.

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

Avec un seul argument itérable, renvoie son élément le plus grand.
Avec deux arguments ou plus, renvoie l'argument le plus grand.

Ainsi, le key=func permet essentiellement de passer un argument facultatif key à la fonction sur la base de laquelle l'itérateur/les arguments donnés sont triés et le maximum est renvoyé.

lambda est un mot-clé Python qui agit comme une pseudo fonction. Ainsi, lorsque vous passez l'objet player à celle-ci, elle renverra player.totalScore. Ainsi, l'itérable passé à la fonction max sera trié selon la clé totalScore des objets player qui lui sont donnés et renverra le player qui a le totalScore maximal.

Si aucun argument key n'est fourni, le maximum est renvoyé selon l'ordre par défaut de Python.

Exemples -

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')

11voto

charmlessCoin Points 406

Comment fonctionne la fonction max?

Elle cherche l'élément "le plus grand" dans un itérable. Je suppose que vous pouvez vérifier ce que c'est, mais sinon, c'est quelque chose que vous pouvez parcourir, c'est-à-dire une liste ou une chaîne.

Quel est l'usage du mot-clé key dans la fonction max? Je sais qu'il est également utilisé dans le contexte de la fonction sort

Key est une fonction lambda qui indiquera à max quels objets dans l'itérable sont plus grands que d'autres. Disons que vous triez un objet que vous avez créé vous-même, et non quelque chose d'obvious, comme des entiers.

Signification de l'expression lambda? Comment les lire? Comment fonctionnent-elles?

C'est un peu une grande question. En termes simples, une lambda est une fonction que vous pouvez transmettre et que d'autres parties de code peuvent utiliser. Prenons cet exemple:

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

Cela prend deux objets, a et b, et une fonction f. Elle appelle f() sur chaque objet, puis les additionne. Regardez cet appel:

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

somme() prend 2, et appelle l'expression lambda dessus. Donc f(a) devient 2 * 2, c'est-à-dire 4. Puis elle fait la même chose pour b, et les additionne.

En termes moins simples, les lambdas viennent du calcul lambda, qui est l'idée d'une fonction qui retourne une fonction; un concept mathématique très intéressant pour exprimer des calculs. Vous pouvez en apprendre plus ici, et ensuite réellement comprendre ça ici.

Il est probablement préférable de se renseigner un peu plus sur ce sujet, car les lambdas peuvent être déroutantes, et leur utilité n'est pas immédiatement évidente. Consultez ici.

6voto

Inbar Rose Points 13033

Selon la documentation:

max(iterable[, key])
max(arg1, arg2, *args[, key])
Renvoie l'élément le plus grand dans un iterable ou le plus grand parmi deux arguments ou plus.

Si un argument positionnel est fourni, l'itérable doit être un itérable non vide (comme une chaîne non vide, un tuple ou une liste). L'élément le plus grand de l'itérable est renvoyé. Si deux arguments positionnels ou plus sont fournis, le plus grand des arguments positionnels est renvoyé.

L'argument clé facultatif spécifie une fonction de tri à un argument comme celle utilisée pour list.sort(). L'argument de clé, s'il est fourni, doit être sous forme de mot-clé (par exemple, max(a,b,c,key=func)).

Ce que cela signifie, c'est que dans votre cas, vous fournissez une liste, dans ce cas players. Ensuite, la fonction max parcourra tous les éléments de la liste et les comparera les uns aux autres pour obtenir un "maximum".

Comme vous pouvez l'imaginer, avec un objet complexe comme un joueur, déterminer sa valeur pour la comparaison est délicat, c'est pourquoi vous disposez de l'argument key pour déterminer comment la fonction max décidera de la valeur de chaque joueur. Dans ce cas, vous utilisez une fonction lambda pour dire "pour chaque p dans players obtenir p.totalscore et utiliser cela comme sa valeur pour la comparaison".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X