web-dev-qa-db-fra.com

Syntaxe derrière triée (clé = lambda: ...)

Je ne comprends pas très bien la syntaxe derrière l'argument sorted():

key=lambda variable: variable[0]

lambda n'est-il pas arbitraire? Pourquoi variable est-il indiqué deux fois dans ce qui ressemble à un dict?

130

key est une fonction qui sera appelée pour transformer les éléments de la collection avant qu'ils ne soient comparés. Le paramètre passé à key doit être un élément appelable.

L'utilisation de lambda crée une fonction anonyme (qui est appelable). Dans le cas de sorted, l'appelable ne prend qu'un paramètre. Le lambda de Python est assez simple. Il ne peut que faire et retourner une chose vraiment.

La syntaxe de lambda est le mot lambda suivi de la liste des noms de paramètres, puis d'un seul bloc de code. La liste des paramètres et le bloc de code sont délimités par deux points. Ceci est similaire aux autres constructions de python, telles que while, for, if et ainsi de suite. Ce sont toutes des déclarations qui ont généralement un bloc de code. Lambda est juste une autre instance d'une instruction avec un bloc de code.

Nous pouvons comparer l’utilisation de lambda à celle de def pour créer une fonction.

adder_lambda = lambda parameter1,parameter2: parameter1+parameter2
def adder_regular(parameter1, parameter2): return parameter1+parameter2

lambda nous donne juste un moyen de faire cela sans donner de nom. Ce qui le rend idéal pour utiliser comme paramètre d'une fonction.

variable est utilisé deux fois ici car sur la gauche des deux points, il s'agit du nom d'un paramètre et sur celui de droite, il est utilisé dans le bloc de code pour calculer quelque chose.

141
Evan

Je pense que toutes les réponses ici couvrent assez bien ce que la fonction lambda fait dans le contexte de sort (), mais je sens toujours qu’il manque une description conduisant à une compréhension intuitive. Voici donc mes deux sous.

Par souci d’exhaustivité, j’énoncerai une évidence dès le départ: trié () retourne une liste d’éléments triés et si nous voulons trier d’une manière particulière ou si nous voulons trier une liste complexe d’éléments (par exemple, des listes imbriquées ou une liste de tuples), nous pouvons invoquer l'argument clé.

Pour moi, la compréhension intuitive de l'argument clé, la raison pour laquelle il doit être appelable, et l'utilisation de lambda en tant que fonction appelable (anonyme) pour y parvenir se présentent en deux parties.

  1. L'utilisation de lamba signifie finalement que vous n'avez pas à écrire (définir) une fonction entière, comme celle sblom en a donné un exemple. Les fonctions Lambda sont créées, utilisées et immédiatement détruites - afin qu'elles n'améliorent pas votre code avec plus de code qui ne sera utilisé qu'une seule fois. Si j'ai bien compris, il s'agit de l'utilitaire principal de la fonction lambda et ses applications pour de tels rôles sont vastes. Sa syntaxe est purement conventionnelle, ce qui est essentiellement la nature de la syntaxe programmatique en général. Apprenez la syntaxe et faites-en.

La syntaxe Lambda est la suivante:

lambda entrée_variable (s) : savoureux un liner

par exemple.

In [1]: f00 = lambda x: x/2

In [2]: f00(10)
Out[2]: 5.0

In [3]: (lambda x: x/2)(10)
Out[3]: 5.0

In [4]: (lambda x, y: x / y)(10, 2)
Out[4]: 5.0

In [5]: (lambda: 'amazing lambda')() # func with no args!
Out[5]: 'amazing lambda'
  1. L'argument sous-jacent à l'argument key est qu'il doit contenir un ensemble d'instructions qui dirigeront essentiellement la fonction 'sort ()' vers les éléments de la liste devant être utilisés pour trier. Quand il est écrit key=, cela signifie en réalité que: Lorsque je parcours la liste un élément à la fois (c’est-à-dire pour e dans la liste), je vais transmettre l’élément actuel à la fonction que je fournis dans la liste. argument clé et utilisez-le pour créer une liste transformée qui m’informera de l’ordre de la liste finale triée.

Vérifiez-le:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=WhatToSortBy)

Exemple de base:

sorted(mylist)

[2, 3, 3, 4, 6, 8, 23] # tous les nombres sont dans l'ordre, du plus petit au plus grand.

Exemple 1:

mylist = [3,6,3,2,4,8,23]
sorted(mylist, key=lambda x: x%2==0)

[3, 3, 23, 6, 2, 4, 8] # Ce résultat trié a-t-il un sens intuitif pour vous?

Notez que ma fonction lambda a ordonné à Trier de vérifier si (e) était pair ou impair avant le tri.

MAIS ATTENDEZ! Vous pouvez (ou peut-être devriez) vous demander deux choses - premièrement, pourquoi mes chances sont-elles avant mes événements (puisque ma valeur clé semble indiquer à ma fonction triée de hiérarchiser les événements en utilisant l'opérateur mod dans x%2==0). Deuxièmement, pourquoi mes soirées sont-elles hors d'usage? 2 vient avant 6 non? En analysant ce résultat, nous en apprendrons un peu plus sur le fonctionnement de l'argument "clé" de sort (), en particulier en liaison avec la fonction anonyme lambda.

Tout d'abord, vous remarquerez que, même si les probabilités se situent avant les événements, les événements eux-mêmes ne sont pas triés. Pourquoi est-ce?? Permet de lire la documentation :

Fonctions de touche À partir de Python 2.4, list.sort () et trié () ont ajouté un paramètre de clé permettant de spécifier une fonction. être appelé sur chaque élément de la liste avant de faire des comparaisons.

Nous devons faire un peu de lecture entre les lignes ici, mais cela nous dit que la fonction de tri n’est appelée qu’une fois, et si nous spécifions l’argument key, nous trions par la valeur indiquée par la fonction key.

Alors, que renvoie l'exemple utilisant un modulo? Une valeur booléenne: True == 1, False == 0. Alors, comment fait le tri avec cette clé? Fondamentalement, il transforme la liste originale en une séquence de 1 et de 0.

[3,6,3,2,4,8,23] devient [0,1,0,1,1,1,0]

Maintenant, nous allons quelque part. Qu'est-ce que vous obtenez lorsque vous triez la liste transformée?

[0,0,0,1,1,1,1]

Ok, alors maintenant nous savons pourquoi les chances sont avant les événements. Mais la question suivante est la suivante: pourquoi le 6 vient-il toujours avant le 2 de ma liste finale? Eh bien c'est facile - c'est parce que le tri ne se produit qu'une fois! C'est-à-dire que les 1 représentent toujours les valeurs de la liste d'origine, qui se trouvent dans leur position d'origine les unes par rapport aux autres. Étant donné que le tri n'a lieu qu'une seule fois et que nous n'appelons aucune fonction de tri pour ordonner les valeurs paires, de bas en haut, ces valeurs restent dans leur ordre d'origine les unes par rapport aux autres.

La dernière question est alors la suivante: comment penser conceptuellement comment l’ordre de mes valeurs booléennes est transformé en valeurs originales lorsque j’imprime la liste triée finale?

Sorted () est une méthode intégrée qui (réalité amusante) utilise un algorithme de tri hybride appelé Timsort qui combine les aspects du tri par fusion et du tri par insertion. Il me semble évident que lorsque vous l'appelez, il existe un mécanisme qui conserve ces valeurs en mémoire et les regroupe avec leur identité booléenne (masque) déterminée par (...!) La fonction lambda. L'ordre est déterminé par leur identité booléenne calculée à partir de la fonction lambda, mais gardez à l'esprit que ces sous-listes (de son et zéros) ne sont pas elles-mêmes triées par leurs valeurs d'origine. Par conséquent, la liste finale, bien qu'organisée par Odds et Evens, n'est pas triée par sous-liste (les evens dans ce cas sont hors d'usage). Le fait que les cotes soient commandées tient au fait qu’elles étaient déjà en ordre par hasard dans la liste initiale. En guise de conclusion, lorsque lambda effectue cette transformation, l'ordre initial des sous-listes est conservé.

Alors, comment tout cela est-il lié à la question initiale, et plus important encore, à notre intuition sur la manière dont nous devrions implémenter Trier () avec son argument clé et lambda?

Cette fonction lambda peut être considérée comme un pointeur pointant sur les valeurs à trier, qu'il s'agisse d'un pointeur mappant une valeur sur son booléen transformé par la fonction lambda ou d'un élément particulier dans une liste imbriquée, Tuple, dict, etc., à nouveau déterminé par la fonction lambda.

Essayons de prédire ce qui se passera lorsque j'exécuterai le code suivant.

mylist = [(3, 5, 8), (6, 2, 8), ( 2, 9, 4), (6, 8, 5)]
sorted(mylist, key=lambda x: x[1])

Mon appel sorted dit évidemment: "Veuillez trier cette liste". L'argument clé rend cela un peu plus précis en disant, pour chaque élément (x) dans mylist, retourne l'index 1 de cet élément, puis trie tous les éléments de la liste originale 'mylist' par la ordre de tri de la liste calculé par la fonction lambda. Comme nous avons une liste de nuplets, nous pouvons retourner un élément indexé à partir de ce nuplet. Nous obtenons donc:

[(6, 2, 8), (3, 5, 8), (6, 8, 5), (2, 9, 4)]

Exécutez ce code et vous constaterez qu'il s'agit de l'ordre. Essayez d’indexer une liste d’entiers et vous constaterez que le code est cassé.

C’était une longue explication, mais j’espère que cela vous aidera à "trier" votre intuition sur l’utilisation des fonctions lambda en tant qu’argument clé dans Trier () et au-delà.

110
PaulG

lambda est un Python mot-clé utilisé pour générer des fonctions anonymes .

>>> (lambda x: x+2)(3)
5
25

Le variable à gauche du : est un nom de paramètre. L'utilisation de variable à droite utilise le paramètre.

Signifie presque exactement la même chose que:

def some_method(variable):
  return variable[0]
12
sblom

lambda est une fonction anonyme, pas une fonction arbitraire. Le paramètre accepté sera la variable avec laquelle vous travaillez et la colonne dans laquelle vous le triez.

3
Makoto

Puisque l'utilisation de lambda a été posée dans le contexte de sorted(), jetez également un coup d'œil à ceci https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

2
Kristof Pal