Función max de python usando ‘key’ y lambda expresión

Vengo de fondo OOP y tratando de aprender python. Estoy usando la función max , que usa una expresión lambda para devolver la instancia de tipo Player tiene el máximo totalScore entre los players la lista.

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

La función devuelve correctamente una instancia de tipo Player con el máximo totalScore . Estoy confundido acerca de las siguientes tres cosas:

  1. ¿Cómo funciona la función max ? ¿Cuáles son los argumentos que está tomando? Miré la documentación pero no entendí.
  2. ¿Cuál es el uso de la clave de palabras key en la función max? Sé que también se usa en el contexto de la función de sort
  3. ¿Significado de la expresión lambda? ¿Cómo leerlos? ¿Cómo trabajan?

Estas son preguntas conceptuales muy nobles, pero me ayudarán a entender el lenguaje. Te ayudaría si pudieras dar ejemplos para explicar. Gracias

lambda es una función anónima, es equivalente a:

 def func(p): return p.totalScore 

Ahora max convierte en:

 max(players, key=func) 

Pero como las declaraciones de def son declaraciones compuestas, no se pueden usar donde se requiere una expresión, es por eso que a veces se usan lambda .

Tenga en cuenta que lambda es equivalente a lo que pondría en una statement de retorno de una def . Por lo tanto, no puede usar sentencias dentro de un lambda , solo se permiten expresiones.


¿Qué hace max ?

max (a, b, c, … [, tecla = func]) -> valor

Con un solo argumento iterable, devuelve su artículo más grande. Con dos o más argumentos, devuelve el argumento más grande.

Por lo tanto, simplemente devuelve el objeto que es el más grande.


¿Cómo funciona la key ?

De forma predeterminada, en Python 2, la key compara los elementos en función de un conjunto de reglas según el tipo de los objetos (por ejemplo, una cadena siempre es mayor que un número entero).

Para modificar el objeto antes de la comparación, o para comparar en función de un atributo / índice en particular, debe usar el argumento key .

Ejemplo 1:

Un ejemplo simple, suponga que tiene una lista de números en forma de cadena, pero desea comparar esos artículos por su valor entero.

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

Aquí max compara los elementos utilizando sus valores originales (las cadenas se comparan de forma lexicográfica, por lo que obtendrías '2' como salida):

 >>> max(lis) '2' 

Para comparar los elementos por su valor entero use la key con un simple lambda :

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

Ejemplo 2: aplicar max a una lista de listas.

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

Por defecto max comparará los artículos por el primer índice. Si el primer índice es el mismo, comparará el segundo índice. Como en mi ejemplo, todos los elementos tienen un primer índice único, por lo que obtendrías esto como la respuesta:

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

Pero, ¿qué sucede si desea comparar cada elemento por el valor en el índice 1? Simple: use lambda :

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

Comparando elementos en una iterable que contiene objetos de diferente tipo :

Lista con artículos mixtos:

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

En Python 2 es posible comparar elementos de dos tipos diferentes :

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

Pero en Python 3 ya no puedes hacer eso :

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

Pero esto funciona, ya que estamos comparando la versión entera de cada objeto:

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

Versión fuertemente simplificada 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 

Respecto a lambda:

 >>> ident = lambda x: x >>> ident(3) 3 >>> ident(5) 5 >>> times_two = lambda x: 2*x >>> times_two(2) 4 

¿Cómo funciona la función max?

Busca el artículo “más grande” en un iterable. Asumiré que puedes buscar lo que es, pero si no, es algo que puedes recorrer, es decir, una lista o una cadena.

¿Cuál es el uso de la clave de palabras clave en la función max? Sé que también se usa en el contexto de la función de clasificación

Key es una función lambda que le dirá a max qué objetos en el iterable son más grandes que otros. Diga si estaba clasificando algún objeto que creó usted mismo, y no algo obvio, como los enteros.

¿Significado de la expresión lambda? ¿Cómo leerlos? ¿Cómo trabajan?

Esa es una especie de pregunta más grande. En términos simples, una lambda es una función que puede pasar , y que otras piezas de código la utilicen. Toma esto por ejemplo:

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

Esto toma dos objetos, a y b , y una función f . Llama a f() en cada objeto, luego los sum. Así que mira esta llamada:

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

sum() toma 2 y llama a la expresión lambda. Entonces f(a) convierte en 2 * 2 , que se convierte en 4. Luego hace esto por b , y sum los dos juntos.

En términos no tan simples, las lambdas provienen del cálculo lambda, que es la idea de una función que devuelve una función; Un concepto matemático muy bueno para express computación. Puedes leer sobre eso aquí , y luego entenderlo aquí .

Probablemente sea mejor leer un poco más sobre esto, ya que las lambdas pueden ser confusas, y no es evidente de inmediato cuán útiles son. Compruebe aquí .

Según la documentación :

max (iterable [, tecla])
max (arg1, arg2, * args [, tecla])
Devuelva el elemento más grande en un iterable o el mayor de dos o más argumentos.

Si se proporciona un argumento posicional, iterable debe ser un iterable no vacío (como una cadena, tupla o lista no vacía). Se devuelve el artículo más grande en el iterable. Si se proporcionan dos o más argumentos posicionales, se devuelve el mayor de los argumentos posicionales.

El argumento de clave opcional especifica una función de ordenamiento de un argumento como la que se usa para list.sort (). El argumento clave, si se proporciona, debe estar en forma de palabra clave (por ejemplo, max (a, b, c, key = func)).

Lo que esto dice es que en su caso, está proporcionando una lista, en este caso, los players . Luego, la función max recorrerá todos los elementos de la lista y los comparará entre sí para obtener un “máximo”.

Como puedes imaginar, con un objeto complejo como un player determinar su valor para la comparación es complicado, por lo que te dan el argumento key para determinar cómo la función max decidirá el valor de cada player . En este caso, está utilizando una función lambda para decir “para cada p en los players obtener p.totalscore y usar eso como su valor para la comparación”.

max función max se utiliza para obtener el máximo de un iterable .

Los iteradores pueden ser listas, tuplas, objetos dict, etc. O incluso objetos personalizados como en el ejemplo que proporcionó.

 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. 

Entonces, key=func básicamente nos permite pasar una key argumento opcional a la función en cuya base se clasifican el iterador / argumentos dados y se devuelve el máximo.

lambda es una palabra clave de python que actúa como una pseudo función. Entonces, cuando le pasas el objeto de player a él, devolverá player.totalScore . Por lo tanto, el iterable pasado a la función max se ordenará de acuerdo con la key totalScore de los objetos del player que se le han totalScore y devolverá al player que tenga el total de totalScore .

Si no se proporciona key argumento key , se devuelve el máximo de acuerdo con los pedidos predeterminados de Python.

Ejemplos –

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

max está integrado en una función que toma el primer argumento como iterable (como lista o tupla)

la clave de argumento de palabra key tiene su valor predeterminado None pero acepta la función para evaluar, considérala como un contenedor que evalúa iterable según la función

Considere este diccionario de ejemplo:

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

Ex:

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

Como puede ver, si solo pasa el iterable sin kwarg (una función a la key ) está devolviendo el valor máximo de la tecla (alfabéticamente)

Ex. En lugar de encontrar el valor máximo de la clave alfabéticamente, es posible que necesite encontrar la clave máxima por la longitud de la clave:

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

en este ejemplo, la función lambda está devolviendo la longitud de la clave, que se iterará, por lo tanto, al evaluar los valores en lugar de considerarlos alfabéticamente, mantendrá un registro de la longitud máxima de la clave y la clave de retornos que tiene la longitud máxima

Ex.

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

en este ejemplo, la función lambda está devolviendo el valor de la clave del diccionario correspondiente que tiene el valor máximo