使用“key”和 lambda 表达式的 python max 函数
- 2025-01-08 08:50:00
- admin 原创
- 109
问题描述:
我有 OOP 背景,正在尝试学习 Python。我正在使用一个max
函数,该函数使用 lambda 表达式返回列表中Player
具有最大值的类型的实例。totalScore
`players`
def winner():
w = max(players, key=lambda p: p.totalScore)
该函数正确返回Player
具有最大值的类型的实例totalScore
。我对以下三件事感到困惑:
这个函数是如何
max
工作的?它所用的参数是什么?我看了文档,但还是不明白。max 函数中关键字的用途是什么
key
?我知道它也用于sort
函数上下文中lambda 表达式的含义?如何理解它们?它们如何工作?
这些都是非常新手的概念性问题,但可以帮助我理解语言。如果你能举例说明,那就更好了。谢谢
解决方案 1:
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'
解决方案 2:
的极简化版本max
:
def max(items, key=lambda x: x):
current = item[0]
for item in items:
if key(item) > key(current):
current = item
return current
关于lambda:
>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5
>>> times_two = lambda x: 2*x
>>> times_two(2)
4
解决方案 3:
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
totalScoreplayer
进行排序,并将返回player
具有最大 的人totalScore
。
如果没有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')
解决方案 4:
max 函数如何工作?
它查找可迭代对象中的“最大”项。我假设您可以查找它是什么,但如果不能,它就是您可以循环遍历的内容,即列表或字符串。
max 函数中关键字 key 有什么用?我知道它也用于 sort 函数中
Key
是一个 lambda 函数,它将告诉max
迭代器中的哪些对象比其他对象大。假设您要对自己创建的对象进行排序,而不是对整数等显而易见的对象进行排序。
lambda 表达式的含义?如何理解它们?它们如何工作?
这是一个比较大的问题。简单来说,lambda 是一个可以传递的函数,并让其他代码段使用它。例如:
def sum(a, b, f):
return (f(a) + f(b))
它需要两个对象a
和b
,以及一个函数f
。它调用f()
每个对象,然后将它们加在一起。看看这个调用:
>>> sum(2, 2, lambda a: a * 2)
8
sum()
取2
,并对其调用 lambda 表达式。因此f(a)
变为2 * 2
,变为 4。然后对 执行此操作b
,并将两者相加。
简单来说,lambda 源自 lambda 演算,即一个函数返回另一个函数的概念;这是一个非常酷的数学概念,用于表达计算。您可以在此处阅读相关内容,然后在此处真正理解它。
最好多读一些这方面的内容,因为 lambda 可能会让人困惑,而且它们的作用并不是很明显。请点击此处。
解决方案 5:
根据文件:
max(iterable[, key])
max(arg1, arg2, *args[, key])
返回可迭代对象中的最大项或两个或多个参数中的最大项。如果提供了一个位置参数,则 iterable 必须是非空的可迭代对象(例如非空的字符串、元组或列表)。将返回可迭代对象中的最大项。如果提供了两个或更多位置参数,则返回位置参数中的最大项。
可选的 key 参数指定一个单参数排序函数,如 list.sort() 中使用的函数。如果提供 key 参数,则必须采用关键字形式(例如,max(a,b,c,key=func))。
这说明,在您的情况下,您提供了一个列表,在本例中为players
。然后,该max
函数将遍历列表中的所有项目并将它们相互比较以获得“最大值”。
可以想象,对于像 这样的复杂对象,player
确定其值以进行比较是很棘手的,因此您需要给出key
参数来确定函数如何max
确定 each 的值。在这种情况下player
,您使用 lambda 函数来表示“获取 eachp
并将其用作其比较值”。players
`p.totalscore`
解决方案 6:
max
内置函数,其第一个参数为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(一个函数)的 iterable key
,它将返回键的最大值(按字母顺序排列)
例如,你可能需要按键的长度查找最大键,而不是按字母顺序查找键的最大值:
>>>max(d.keys(), key=lambda x: len(x))
'artwork'
在这个例子中,lambda 函数返回将被迭代的键的长度,因此在评估值时,它将跟踪键的最大长度,而不是按字母顺序考虑,并返回具有最大长度的键
前任。
>>> max(d.keys(), key=lambda x: d[x])
'friend'
在此示例中,lambda 函数返回具有最大值的相应字典键的值。
解决方案 7:
这有助于我理解这种模式的工作原理。将密钥视为转换函数/比较指标。
max(data, lambda x: transform_function(x))
这是什么意思呢?假设我们有一个数字列表 [1, 2, 3, 4, 5]。我们的任务是找到正弦结果最大的值。
我们不用将 max 函数应用到数字列表,而是用转换函数转换每个值(这里sin
)
1 -> sin(1)
2 -> sin(2)
3 -> sin(3)
4 -> sin(4)
5 -> sin(5)
现在,我们对转换后的值应用 max 函数。这将得到sin(2)
,这是输入 2 的结果,因此max(numbers, lambda x: sin(x))
将返回 2。
让我们将这个想法应用到更复杂的情况中。考虑以下词典(例如,有三个温度测量值的城市):
cities = {
"New York": [10, 12, 13],
"Los Angeles": [14, 15, 16],
"Washington": [8, 5, -1],
}
我们的目标是找到温度最高的城市(应该是Los Angeles
)。我们需要应用什么适当的变换?用文字表达就是:我们想要看到max
温度的 = cities[city]
,因此max(cities[city])
应该是我们的变换。所以我们需要执行以下操作。
max(cities, key=lambda city: max(cities[city]))
您甚至可以使用嵌套字典来实现这一点。
cities: dict = {
"New York": {
"temperatures": [1, 2, 9],
"populations": [10000, 20000, 30000],
},
"Los Angeles": {
"temperatures": [4, 5, 4],
"populations": [40000, 50000, 60000],
},
"Washington": {
"temperatures": [1, 0, -1],
"populations": [10000, 1000, 0],
}
}
max(cities, key=lambda city: max(cities[city]["populations"]))
解决方案 8:
假设访问此页面的人确实想知道key=
其中的内容len()
,那么这里有一个简单的答案:
len()
计算对象的长度。如果我们len
在 中指定为键函数min()
,max()
它将根据其长度返回最小/最大项目。
food = ['bread', 'tea', 'banana', 'kiwi', 'tomato']
print(max(food, key=len)) # banana
print(min(food, key=len)) # tea
扫码咨询,免费领取项目管理大礼包!