使用’key’和lambda表达式的python max函数

问题:使用’key’和lambda表达式的python max函数

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

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

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

  1. max功能如何工作?它正在采取什么论点?我查看了文档,但听不懂。
  2. keymax函数中关键字的用途是什么?我知道它也用于sort功能上下文
  3. lambda表达式的含义?如何阅读它们?它们如何运作?

这些都是非常笨拙的概念性问题,但可以帮助我理解语言。如果您可以提供示例进行解释,将有所帮助。谢谢

I come from OOP background and trying to learn python. I am using the max function which uses a lambda expression to return the instance of type Player having maximum totalScore among the list players.

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

The function correctly returns instance of type Player having maximum totalScore. I am confused about the following three things:

  1. How does the max function work? What are the arguments it is taking? I looked at the documentation but failed to understand.
  2. What is use of the keyword key in max function? I know it is also used in context of sort function
  3. Meaning of the lambda expression? How to read them? How do they work?

These are all very noobish conceptual questions but will help me understand the language. It would help if you could give examples to explain. Thanks


回答 0

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

def func(p):
   return p.totalScore     

现在max变成:

max(players, key=func)

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

请注意,这lambda等效于您在的return语句中输入的内容def。因此,您不能在内使用语句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'

lambda is an anonymous function, it is equivalent to:

def func(p):
   return p.totalScore     

Now max becomes:

max(players, key=func)

But as def statements are compound statements they can’t be used where an expression is required, that’s why sometimes lambda‘s are used.

Note that lambda is equivalent to what you’d put in a return statement of a def. Thus, you can’t use statements inside a lambda, only expressions are allowed.


What does max do?

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.

So, it simply returns the object that is the largest.


How does key work?

By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).

To modify the object before comparison, or to compare based on a particular attribute/index, you’ve to use the key argument.

Example 1:

A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.

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

Here max compares the items using their original values (strings are compared lexicographically so you’d get '2' as output) :

>>> max(lis)
'2'

To compare the items by their integer value use key with a simple lambda:

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

Example 2: Applying max to a list of tuples.

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

By default max will compare the items by the first index. If the first index is the same then it’ll compare the second index. As in my example, all items have a unique first index, so you’d get this as the answer:

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

But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:

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

Comparing items in an iterable that contains objects of different type:

List with mixed items:

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

In Python 2 it is possible to compare items of two different types:

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

But in Python 3 you can’t do that any more:

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

But this works, as we are comparing integer version of each object:

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

回答 1

的高度简化版本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

Strongly simplified version of max:

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

Regarding lambda:

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

>>> times_two = lambda x: 2*x
>>> times_two(2)
4

回答 2

max函数如何工作?

它寻找可迭代的“最大”项。我假设您可以查找内容,但如果不是,则可以循环查找,即列表或字符串。

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,并将两者加在一起。

用不那么简单的术语来说,lambda来自lambda演算,这是一个返回函数的函数。用于表达计算的非常酷的数学概念。你可以阅读有关在这里,然后居然明白在这里

最好多读一遍,因为lambda可能会造成混淆,而且还不清楚它们的用处。在这里检查。

How does the max function work?

It looks for the “largest” item in an iterable. I’ll assume that you can look up what that is, but if not, it’s something you can loop over, i.e. a list or string.

What is use of the keyword key in max function? I know it is also used in context of sort function

Key is a lambda function that will tell max which objects in the iterable are larger than others. Say if you were sorting some object that you created yourself, and not something obvious, like integers.

Meaning of the lambda expression? How to read them? How do they work?

That’s sort of a larger question. In simple terms, a lambda is a function you can pass around, and have other pieces of code use it. Take this for example:

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

This takes two objects, a and b, and a function f. It calls f() on each object, then adds them together. So look at this call:

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

sum() takes 2, and calls the lambda expression on it. So f(a) becomes 2 * 2, which becomes 4. It then does this for b, and adds the two together.

In not so simple terms, lambdas come from lambda calculus, which is the idea of a function that returns a function; a very cool math concept for expressing computation. You can read about that here, and then actually understand it here.

It’s probably better to read about this a little more, as lambdas can be confusing, and it’s not immediately obvious how useful they are. Check here.


回答 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。因此,传递给函数的iterable max将根据提供给它的对象的key totalScore进行排序,player并返回player具有maximum 的who 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')

max function is used to get the maximum out of an iterable.

The iterators may be lists, tuples, dict objects, etc. Or even custom objects as in the example you provided.

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.

So, the key=func basically allows us to pass an optional argument key to the function on whose basis is the given iterator/arguments are sorted & the maximum is returned.

lambda is a python keyword that acts as a pseudo function. So, when you pass player object to it, it will return player.totalScore. Thus, the iterable passed over to function max will sort according to the key totalScore of the player objects given to it & will return the player who has maximum totalScore.

If no key argument is provided, the maximum is returned according to default Python orderings.

Examples –

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(iterable [,key])
max(arg1,arg2,* args [,key])
返回可迭代的最大项目或两个或多个参数中的最大项目。

如果提供了一个位置参数,则iterable必须是非空的Iterable(例如,非空的字符串,元组或列表)。返回iterable中最大的项目。如果提供了两个或多个位置自变量,则返回最大的位置自变量。

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

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

可以想象,使用复杂的对象(例如player确定其比较值)比较棘手,因此将为您提供key参数,以确定max函数如何确定每个对象的值player。在这种情况下,您使用的是lambda函数,说“对于每个pin playersget p.totalscore并将其用作比较的值”。

According to the documentation:

max(iterable[, key])
max(arg1, arg2, *args[, key])
Return the largest item in an iterable or the largest of two or more arguments.

If one positional argument is provided, iterable must be a non-empty iterable (such as a non-empty string, tuple or list). The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.

The optional key argument specifies a one-argument ordering function like that used for list.sort(). The key argument, if supplied, must be in keyword form (for example, max(a,b,c,key=func)).

What this is saying is that in your case, you are providing a list, in this case players. Then the max function will iterate over all the items in the list and compare them to each other to get a “maximum”.

As you can imagine, with a complex object like a player determining its value for comparison is tricky, so you are given the key argument to determine how the max function will decide the value of each player. In this case, you are using a lambda function to say “for each p in players get p.totalscore and use that as his value for comparison”.


回答 5

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的可迭代对象(将函数传递给key),它将返回key的最大值(按字母顺序)

例如 可能不是需要按字母顺序查找键的最大值,而是可能需要根据键的长度查找最大键:

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

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

例如

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

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

max is built in function which takes first argument an iterable (like list or tuple)

keyword argument key has it’s default value None but it accept function to evaluate, consider it as wrapper which evaluates iterable based on function

Consider this example dictionary:

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

Ex:

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

As you can see if you only pass the iterable without kwarg(a function to key) it is returning maximum value of key(alphabetically)

Ex. Instead of finding max value of key alphabetically you might need to find max key by length of key:

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

in this example lambda function is returning length of key which will be iterated hence while evaluating values instead of considering alphabetically it will keep track of max length of key and returns key which has max length

Ex.

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

in this example lambda function is returning value of corresponding dictionary key which has maximum value