función max de python usando 'key' y expresión lambda

180

Vengo de fondo OOP y trato de aprender Python. Estoy usando la maxfunción que usa una expresión lambda para devolver la instancia de tipo que Playertiene el máximo totalScoreentre la lista players.

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

La función devuelve correctamente la instancia de tipo que Playertiene un máximo totalScore. Estoy confundido acerca de las siguientes tres cosas:

  1. ¿Cómo funciona la maxfunción? ¿Cuáles son los argumentos que está tomando? Miré la documentación pero no pude entender.
  2. ¿Para qué sirve la palabra clave keyen la función max? Sé que también se usa en el contexto de la sortfunción.
  3. Significado de la expresión lambda? ¿Cómo leerlos? ¿Cómo trabajan?

Todas estas son preguntas conceptuales muy novatas, pero me ayudarán a entender el lenguaje. Sería útil si pudiera dar ejemplos para explicar. Gracias

Vijay
fuente
¿Qué versión de Python?
charmlessCoin
2
¿Has consultado la documentación ?
Inbar Rose
@charmlessCoin python 2.7.5
Vijay
2
@InbarRose Revisé la documentación para la función máxima. Realmente no lo entendí.
Vijay
10
@InbarRose Esta página es actualmente el mejor resultado para Google python max lambday quizás pueda ser más útil para los nuevos usuarios.
Mark

Respuestas:

277

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

def func(p):
   return p.totalScore     

Ahora se maxconvierte en:

max(players, key=func)

Pero como las defdeclaraciones son declaraciones compuestas, no se pueden usar donde se requiere una expresión, por eso a veces lambdase usan las.

Tenga en cuenta que lambdaes equivalente a lo que pondría en una declaración de devolución de a def. Por lo tanto, no puede usar declaraciones dentro de a lambda, solo se permiten expresiones.


¿Qué maxhacer?

max (a, b, c, ... [, clave = func]) -> valor

Con un único argumento iterable, devuelve su elemento más grande. Con dos o más argumentos, devuelve el argumento más grande.

Entonces, simplemente devuelve el objeto que es el más grande.


Como keyfunciona

De manera predeterminada, en Python 2 keycompara elementos basados ​​en un conjunto de reglas basadas en el tipo de objetos (por ejemplo, una cadena siempre es mayor que un entero).

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

Ejemplo 1:

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

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

Aquí se maxcomparan los elementos utilizando sus valores originales (las cadenas se comparan lexicográficamente para que se obtenga '2'como salida):

>>> max(lis)
'2'

Para comparar los elementos por su valor entero, use keyuno simple lambda:

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

Ejemplo 2: Aplicar maxa una lista de tuplas.

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

Por defecto maxcomparará los elementos 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ía esto como respuesta:

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

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

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

Comparar elementos en un iterable que contiene objetos de diferente tipo :

Lista con elementos 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 "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
    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'
Ashwini Chaudhary
fuente
Creo que esto es viejo, pero tenía una pregunta al respecto. Veo para la función lambda, la variable xo yo cualquier otra cosa siempre representa el valor en ese índice en la lista. ¿Esta iteración la realiza la función max o la lambda? ¿Las funciones lambda siempre iteran sobre los valores posibles? Por ejemplo: lengths = map(lambda word: len(word), words)donde words=['It', 'is', 'raining', 'cats', 'and', 'dogs']veo que la lambda está iterando sobre cada palabra en la lista. ¿Siempre hace esto?
Mo2
1
@ Mo2 La iteración se realiza mediante maxnot lambda( keyarg es opcional), y durante la iteración, cada elemento se pasa a la función especificada keyy el valor devuelto se utiliza para la comparación.
Ashwini Chaudhary
2
Solo para las personas que vinieron aquí buscando en Google "parámetro de clave máxima". max(lis, key=lambda x:int(x))se puede simplificar como max(lis, key=int). Python tiene una función incorporada, int (). Del mismo modo, puede usar cualquier otra función incorporada como keyargumento. Por ejemplo, puede obtener la cadena más larga de lis=['a', 'aa', 'aaa']pormax(lis, key=len)
YOUNG
1
@YOUNG Nos puede utilizar cualquier función como argumento clave no sólo incorporado funciones, la única condición es que la función debe aceptar los artículos que se le pasan por max, min, sortedetc correctamente. Además, he mencionado max(lis, key=int)justo al final. :-)
Ashwini Chaudhary
@Ashwini Chaudhary ... supongamos que tengo una lista como [1,2,3,4,5]. Aquí todos los artículos son diferentes. Estoy usando la función dada max (set (mylist), key = mylist.count) para encontrar los elementos más frecuentes. ya que en este caso no hay elemento que se repita. Está devolviendo el artículo más bajo. ¿Podemos hacer algo para que devuelva cero o nulo en tal caso?
vikrant rana
12

Versión muy 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

En cuanto a lambda:

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

>>> times_two = lambda x: 2*x
>>> times_two(2)
4
Markus Unterwaditzer
fuente
10

¿Cómo funciona la función max?

Busca el elemento "más grande" en un iterable. Asumiré que puedes buscar qué es eso, pero si no, es algo que puedes recorrer, es decir, una lista o cadena.

¿Para qué sirve 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

Keyes una función lambda que le dirá maxqué objetos en el iterable son más grandes que otros. Di si estabas ordenando algún objeto que creaste tú mismo, y no algo obvio, como los enteros.

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

Esa es una pregunta más grande. En términos simples, una lambda es una función que puede pasar y hacer que otros códigos la usen. Toma esto por ejemplo:

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

Esto toma dos objetos, ay b, y una función f. Llama f()a cada objeto, luego los agrega. Entonces mira esta llamada:

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

sum()toma 2, y llama a la expresión lambda en él. Entonces se f(a)convierte en 2 * 2, que se convierte en 4. Luego hace esto por by suma 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 expresar la computación. Usted puede leer acerca de que aquí , y luego en realidad entender que aquí .

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

sin encanto
fuente
7

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

Los iteradores pueden ser listas, tuplas, objetos dictados, 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=funcbásicamente nos permite pasar un argumento opcionalkey a la función sobre cuya base se ordenan los iteradores / argumentos dados y se devuelve el máximo.

lambdaes una palabra clave de python que actúa como una pseudo función. Entonces, cuando le pasas un playerobjeto, regresará player.totalScore. Por lo tanto, el iterable pasado a la función maxse ordenará de acuerdo con el key puntaje total de los playerobjetos que se le otorguen y devolverá playerquién tiene el máximototalScore .

Si no keyse proporciona ningún argumento, el máximo se devuelve 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')
shad0w_wa1k3r
fuente
6

De acuerdo con la documentación :

max (iterable [, clave])
max (arg1, arg2, * args [, clave])
Devuelve el elemento más grande en un iterable o el más grande 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 elemento 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 clave opcional especifica una función de orden de un argumento como la utilizada 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 está diciendo es que en su caso, está proporcionando una lista, en este caso players. Luego, la maxfunción iterará sobre todos los elementos de la lista y los comparará entre sí para obtener un "máximo".

Como puede imaginar, con un objeto complejo como playerdeterminar su valor de comparación es complicado, por lo que se le da el keyargumento para determinar cómo la maxfunción decidirá el valor de cada uno player. En este caso, está utilizando una función lambda para decir "para cada uno pen playersobtener p.totalscorey usar eso como su valor para la comparación".

Inbar Rose
fuente
3

max está construido en una función que toma un primer argumento iterable (como list o tuple)

El argumento de la palabra clave keytiene su valor predeterminado Nonepero acepta la función para evaluar, considérelo como un contenedor que evalúa iterable en función de 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 para key), está devolviendo el valor máximo de la clave (alfabéticamente)

Ex. En lugar de encontrar el valor máximo de la clave alfabéticamente, es posible que deba 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 repetirá, por lo tanto, al evaluar los valores en lugar de considerarla alfabéticamente, realizará un seguimiento de la longitud máxima de la clave y devolverá la clave 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 de diccionario correspondiente que tiene el valor máximo

Gahan
fuente