Sintaxis detrás ordenada (clave = lambda:…)

No entiendo muy bien la syntax detrás del argumento sorted() :

 key=lambda variable: variable[0] 

¿No es la lambda arbitraria? ¿Por qué se indica la variable dos veces en lo que parece un dict ?

key es una función que se llamará para transformar los elementos de la colección antes de que se comparen. El parámetro pasado a key debe ser algo que sea llamable.

El uso de lambda crea una función anónima (que se puede llamar). En el caso de sorted lo llamable solo toma un parámetro. La lambda de Python es bastante simple. Solo se puede hacer y devolver una cosa de verdad.

La syntax de lambda es la palabra lambda seguida de la lista de nombres de parámetros y luego un solo bloque de código. La lista de parámetros y el bloque de código están delineados por dos puntos. Esto es similar a otras construcciones en python, como por ejemplo, while , for , if y así sucesivamente. Son todas las declaraciones que normalmente tienen un bloque de código. Lambda es simplemente otra instancia de una statement con un bloque de código.

Podemos comparar el uso de lambda con el de def para crear una función.

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

lambda solo nos da una manera de hacer esto sin asignar un nombre. Lo que lo hace ideal para usar como un parámetro para una función.

variable se usa dos veces aquí porque en la mano izquierda de los dos puntos es el nombre de un parámetro y en el lado derecho se usa en el bloque de código para calcular algo.

Creo que todas las respuestas aquí cubren el núcleo de lo que hace la función lambda en el contexto de ordenado () bastante bien, sin embargo, todavía siento que falta una descripción que lleve a una comprensión intuitiva, así que aquí están mis dos centavos.

En aras de la integridad, declararé lo obvio desde el principio: ordenado () devuelve una lista de elementos ordenados y si queremos clasificarlos de una manera particular o si queremos ordenar una lista compleja de elementos (por ejemplo, listas anidadas o una lista de tuplas) podemos invocar el argumento clave.

Para mí, la comprensión intuitiva del argumento clave, por qué debe ser invocable, y el uso de lambda como la función invocable (anónima) para lograr esto se presenta en dos partes.

  1. El uso de lamba en última instancia significa que no tiene que escribir (definir) una función completa, como la que sblom proporcionó como ejemplo. Las funciones Lambda se crean, se usan y se destruyen de inmediato, por lo que no modifican su código con más código que solo se utilizará una vez. Esto, como lo entiendo, es la utilidad principal de la función lambda y sus aplicaciones para tales roles son amplias. Su syntax es puramente convencional, que es en esencia la naturaleza de la syntax programática en general. Aprende la syntax y termina con ella.

La syntax de Lambda es la siguiente:

lambda input_variable (s) : sabroso un forro

p.ej

 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. La idea detrás del argumento key es que debería incluir un conjunto de instrucciones que esencialmente apuntarán a la función ‘ordenada ()’ a aquellos elementos de la lista que deberían usarse para ordenar. Cuando dice key= , lo que realmente significa es: a medida que recorro la lista un elemento a la vez (es decir, para e en la lista), pasaré el elemento actual a la función que proporciono en el argumento clave y utilícelo para crear una lista transformada que me informará sobre el orden de la lista final ordenada.

Echale un vistazo:

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

Ejemplo de base:

 sorted(mylist) 

[2, 3, 3, 4, 6, 8, 23] # todos los números están en orden de pequeño a grande.

Ejemplo 1:

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

[3, 3, 23, 6, 2, 4, 8] # ¿Este resultado clasificado tiene sentido intuitivo para usted?

Observe que mi función lambda ordenó que se verificara si (e) era par o impar antes de ordenar.

¡PERO ESPERA! Puedes (o quizás deberías) preguntarte dos cosas: primero, ¿por qué mis probabilidades están antes que mis pares (ya que mi valor clave parece ser que mi función ordenada debe priorizar los niveladores al usar el operador mod en x%2==0 ) . Segundo, ¿por qué mis eventos están fuera de orden? 2 viene antes de 6 ¿verdad? Al analizar este resultado, aprenderemos algo más profundo acerca de cómo funciona el argumento ‘clave’ ordenado (), especialmente en conjunción con la función lambda anónima.

En primer lugar, notará que mientras las probabilidades están antes que los eventos, los eventos en sí no están ordenados. ¿¿Por qué es esto?? Vamos a leer los documentos :

Funciones clave Comenzando con Python 2.4, tanto list.sort () como sorted () agregaron un parámetro clave para especificar una función a la que llamar en cada elemento de la lista antes de hacer comparaciones.

Tenemos que leer un poco entre líneas aquí, pero lo que esto nos dice es que la función de clasificación solo se llama una vez, y si especificamos el argumento clave, ordenamos por el valor al que nos apunta la función clave.

Entonces, ¿qué hace el ejemplo con un módulo de retorno? Un valor booleano: True == 1 , False == 0 . Entonces, ¿cómo lidiar con esta clave ordenada? Básicamente, transforma la lista original en una secuencia de 1s y 0s.

[3,6,3,2,4,8,23] se convierte en [0,1,0,1,1,1,0]

Ahora estamos llegando a alguna parte. ¿Qué obtienes cuando ordenas la lista transformada?

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

Bien, ahora sabemos por qué las probabilidades están antes que los emparejamientos. Pero la siguiente pregunta es: ¿por qué los 6 siguen antes que los 2 en mi lista final? Bueno, eso es fácil, ¡es porque la clasificación solo ocurre una vez! Es decir, esos 1s todavía representan los valores de la lista original, que están en sus posiciones originales en relación entre sí. Dado que la clasificación solo se realiza una vez, y no llamamos a ningún tipo de función de clasificación para ordenar los valores pares originales de bajo a alto, esos valores permanecen en su orden original uno con respecto al otro.

La pregunta final es la siguiente: ¿cómo pienso conceptualmente acerca de cómo el orden de mis valores booleanos se transforma nuevamente en los valores originales cuando imprimo la lista ordenada final?

Sorted () es un método incorporado que (hecho curioso ) utiliza un algoritmo de clasificación híbrido llamado Timsort que combina aspectos de clasificación de combinación y clasificación de inserción. Me parece claro que cuando lo llamas, hay un mecánico que guarda estos valores en la memoria y los agrupa con su identidad booleana (máscara) determinada por (…!) La función lambda. El orden está determinado por su identidad booleana calculada a partir de la función lambda, pero tenga en cuenta que estos sublistas (de uno y ceros) no están clasificados por sus valores originales. Por lo tanto, la lista final, mientras está organizada por Odds and Evens, no está ordenada por sublista (los eventos en este caso están fuera de orden). El hecho de que las probabilidades están ordenadas es porque ya estaban en orden por coincidencia en la lista original. La conclusión de todo esto es que cuando lambda realiza esa transformación, se conserva el orden original de los sublistas.

Entonces, ¿cómo se relaciona todo esto con la pregunta original y, lo que es más importante, con nuestra intuición sobre cómo debemos implementar ordenado () con su argumento clave y lambda?

Se puede pensar que la función lambda es un puntero que apunta a los valores que necesitamos ordenar, ya sea un puntero que asigna un valor a su valor booleano transformado por la función lambda, o si es un elemento particular en una lista anidada, tupla, dict, etc., nuevamente determinada por la función lambda.

Vamos a intentar y predecir lo que sucede cuando ejecuto el siguiente código.

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

Mi llamada sorted obviamente dice: “Por favor, ordene esta lista”. El argumento clave lo hace un poco más específico al decir que, para cada elemento (x) en mylist, devuelva el índice 1 de ese elemento, luego ordene todos los elementos de la lista original ‘mylist’ por el orden ordenado de la lista calculada por La función lambda. Como tenemos una lista de tuplas, podemos devolver un elemento indexado de esa tupla. Así obtenemos:

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

Ejecute ese código, y encontrará que este es el orden. Intente indexar una lista de enteros y encontrará que el código se rompe.

Esta fue una larga explicación, pero espero que esto ayude a “ordenar” su intuición sobre el uso de las funciones lambda como el argumento clave en ordenado () y más allá.

lambda es una palabra clave de Python que se utiliza para generar funciones anónimas .

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

La variable izquierda de la : es un nombre de parámetro. El uso de la variable de la derecha es hacer uso del parámetro.

Significa casi exactamente lo mismo que:

 def some_method(variable): return variable[0] 

lambda es una función anónima, no una función arbitraria. El parámetro que se acepta sería la variable con la que está trabajando y la columna en la que lo está clasificando.

Dado que el uso de lambda se solicitó en el contexto de sorted() , también vea esto https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions