238

我来自 OOP 背景并尝试学习 python。我正在使用max使用 lambda 表达式的函数来返回列表中Player具有最大值的类型的实例。totalScoreplayers

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

Player该函数正确返回具有最大值的类型的实例totalScore。我对以下三件事感到困惑:

  1. 该功能如何max工作?它的论据是什么?我查看了文档,但未能理解。
  2. keymax函数中的关键字有什么用?我知道它也用于sort函数上下文
  3. lambda 表达式的含义?如何阅读它们?它们是如何工作的?

这些都是非常无聊的概念性问题,但会帮助我理解语言。如果你能举出例子来解释会有所帮助。谢谢

4

6 回答 6

351

lambda是一个匿名函数,它等价于:

def func(p):
   return p.totalScore     

现在max变成:

max(players, key=func)

但是由于def语句是复合语句,它们不能用于需要表达式的地方,这就是有时lambda使用 's 的原因。

请注意,这lambda相当于您在 a 的 return 语句中放入的内容def。因此,您不能在 a 中使用语句lambda,只允许使用表达式。


做什么max

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

使用单个可迭代参数,返回其最大的项目。使用两个或更多参数,返回最大的参数。

因此,它只是返回最大的对象。


如何key工作?

默认情况下,在 Python 2中,基于对象类型的一组规则key比较项目(例如,字符串总是大于整数)。

要在比较之前修改对象,或根据特定属性/索引进行比较,您必须使用key参数。

示例 1:

一个简单的例子,假设你有一个字符串形式的数字列表,但是你想通过它们的整数值来比较这些项目。

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

这里max使用它们的原始值比较项目(字符串是按字典顺序比较的,所以你会得到'2'输出):

>>> max(lis)
'2'

要通过它们的整数值比较项目,请使用key简单的lambda

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

示例 2:应用于max元组列表。

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

默认情况下max,将按第一个索引比较项目。如果第一个索引相同,那么它将比较第二个索引。在我的示例中,所有项目都有一个唯一的第一个索引,所以你会得到这个答案:

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

但是,如果您想通过索引 1 处的值比较每个项目怎么办?简单:使用lambda

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

比较包含不同类型对象的迭代中的项目

包含混合项目的列表:

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

在 Python 2 中,可以比较两种不同类型的项目

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

但是在 Python 3 中你不能再这样做了

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

但这有效,因为我们正在比较每个对象的整数版本:

>>> max(lis, key=lambda x: int(x))  # or simply `max(lis, key=int)`
'111'
于 2013-08-18T07:41:34.417 回答
19

的强烈简化版本max

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

关于拉姆达:

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

>>> times_two = lambda x: 2*x
>>> times_two(2)
4
于 2013-08-18T07:40:47.677 回答
12

max函数用于从iterable.

迭代器可能是列表、元组、字典对象等。甚至是您提供的示例中的自定义对象。

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.

因此,key=func基本上允许我们将一个可选参数传递key给函数,其基础是给定的迭代器/参数被排序并返回最大值。

lambda是一个充当伪函数的python关键字。因此,当您将player对象传递给它时,它将返回player.totalScore. 因此,传递给函数的可迭代对象将根据给它的对象的总分数max进行排序,并返回拥有最大值的对象。key playerplayertotalScore

如果未key提供参数,则根据默认 Python 排序返回最大值。

例子 -

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')
于 2013-08-18T07:49:28.153 回答
11

最大功能如何工作?

它在可迭代对象中查找“最大”项。我假设您可以查找它是什么,但如果不是,它是您可以循环的东西,即列表或字符串。

max 函数中的关键字 key 有什么用?我知道它也用于排序功能的上下文中

Key是一个 lambda 函数,它将告诉max迭代中哪些对象比其他对象大。假设您正在对自己创建的对象进行排序,而不是像整数这样明显的对象。

lambda 表达式的含义?如何阅读它们?它们是如何工作的?

这是一个更大的问题。简单来说,lambda 是一个可以传递的函数,并且可以让其他代码片段使用它。以此为例:

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

这需要两个对象,ab,和一个函数f。它调用f()每个对象,然后将它们加在一起。所以看看这个调用:

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

sum()接受2, 并在其上调用 lambda 表达式。所以f(a)变成2 * 2,变成 4。然后它对 执行此操作b,并将两者相加。

用不那么简单的术语来说,lambdas 来自 lambda calculus,即函数返回函数的思想;一个非常酷的数学概念,用于表达计算。你可以在这里阅读,然后在这里真正理解它。

多读一点可能会更好,因为 lambdas 可能会令人困惑,而且它们的用处并不是很明显。在这里检查。

于 2013-08-18T07:46:13.030 回答
6

根据文档

max(iterable[, key])
max(arg1, arg2, *args[, key])
返回可迭代的最大项或两个或多个参数中的最大项。

如果提供了一个位置参数,则可迭代对象必须是非空可迭代对象(例如非空字符串、元组或列表)。返回可迭代对象中最大的项目。如果提供了两个或更多位置参数,则返回最大的位置参数。

可选的 key 参数指定一个单参数排序函数,类似于 list.sort() 中使用的排序函数。如果提供了 key 参数,则必须采用关键字形式(例如,max(a,b,c,key=func))。

这就是说,在您的情况下,您正在提供一个列表,在这种情况下players。然后该max函数将遍历列表中的所有项目并将它们相互比较以获得“最大值”。

可以想象,对于一个复杂的对象,比如player确定它的比较值是很棘手的,所以给你一个key参数来确定max函数将如何决定 each 的值player。在这种情况下,您正在使用 lambda 函数来表示“对于getp中的每个并将其用作他的比较值”。playersp.totalscore

于 2013-08-18T07:41:16.837 回答
5

max内置函数,它接受第一个参数 an iterable(如列表或元组)

关键字参数key有它的默认值None,但它接受函数来评估,将其视为基于函数评估可迭代的包装器

考虑这个示例字典:

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

前任:

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

正如您所看到的,如果您只传递没有 kwarg(一个函数key)的迭代,它会返回键的最大值(按字母顺序)

前任。您可能需要按键的长度查找最大键,而不是按字母顺序查找键的最大值:

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

在此示例中,lambda 函数返回将被迭代的键的长度,因此在评估值而不是按字母顺序考虑时,它将跟踪键的最大长度并返回具有最大长度的键

前任。

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

在此示例中,lambda 函数返回具有最大值的对应字典键的值

于 2018-04-17T06:38:36.303 回答