如果可能,请详细说明此代码的工作原理。我在论坛上发现了一个类似的问题,但没有解释。(我用lambda找到了很多解决方案,但完全不清楚。lambdas被搁置了很长时间,直到所有材料都很好吸收。)不要严格判断- 我是初学者。
这就是为什么不带括号调用 mykey() 函数的原因吗?这个函数实际上发生了什么?
如果函数返回字符串'age',那为什么不直接写key = 'age'呢?为什么这会引发错误?我阅读了 Byte of Python,几乎所有内容都 99% 清晰,除了这一刻,它通过 lambda 解决。
为什么所有函数都用括号调用?为什么调用不带括号的函数总是(在这种情况下除外)会导致错误,但这里是相反的?一切都很顺利,直到我遇到这个 #@%# 什么是函数对象?foo() 和只是 foo 有什么区别?这些时刻我都不清楚,也没有找到明确的解释。本书中也没有:-(
x = [{'name' : 'Homer', 'age' : 39}, {'name' : 'Bart', 'age' : 100}]
def mykey(a):
return a['age']
print(sorted(x, key = mykey))
很多问题,但我会尽力回答。
都是 sorted 函数,它以函数作为 key 参数,如手册中所写: 可迭代对象也可以通过 key 参数中指定的函数进行排序。它可能是:
带描述的链接已排序
该函数返回年龄,但如果你写它不会直接工作,例如
因为 他应该在输入时一次接收一个,如下所示:
答案给出了高一点,因为应该有一个函数作为参数。
我希望我能够解释一些事情。
该函数不返回字符串
'age',而是接收字典作为输入,并通过 key 返回该字典中写入的内容'age'。例子:
没有括号 - 因为这个函数不是直接调用的,而是作为一个对象在函数内部传递
sorted,并且在它内部已经为每个排序的元素调用,那么结果值被用作排序键(对象的值已排序)。在这种情况下,从列表的每个元素中提取年龄,然后按年龄排序。好吧,如果,作为一个非常遥远的类比,你可以想象一个函数对象就像一辆停在任何地方的公共汽车。函数调用(带括号)是将人加载到总线(函数参数),他去了,把人带到了某个地方——函数被执行了,得到了一些结果。
将一个不带括号的函数传递给另一个函数——你把公共汽车卖给了一些将载人的公司。同时,您自己并没有将这辆公共汽车送上飞机,您只是将它“卖”给了某个公司。
为什么这段代码不起作用:
因为在这里我们自己在航班上发送了“公共汽车”,我们试图“出售”这次调度的结果,而不是“公共汽车”本身。
Lambda 只是一个未命名的函数。您可以将 lambda 写入变量,它将像普通函数一样工作,即:
它不会抛出错误,只是“公共汽车”不会去任何地方:)
仅当您自己在航班上发送它(用括号调用函数)或其他人这样做(您将函数传递到将用括号调用该函数的地方)时,它才会起作用。
这样做的原因是该函数
sorted是一个库函数,旨在对任何对象进行排序。好吧,也就是说,标准库的作者在编写它时,是为了使它可以用于任何对象的列表。如果你想一想,对于排序对象的功能,你只需要知道列表本身和比较两个对象的方法,这样对于任何两个对象,你都可以分辨出哪个更大,哪个更小。
假设您为普通数字编写了一个排序函数,它工作得很好,速度很快,每个人都很开心。现在您需要对字典进行排序。排序算法本身不会因为对象发生变化而改变。唯一改变的是列表元素在算法中的比较方式。
你可能会问“好吧,我正在传递一个字典,为什么不让我指定字典中的键来排序?”
再次,原因是多功能性。如果您不仅要按 排序
age,而且要先按排序age,如果年龄相同,那么您希望这些字典按字母顺序排列name吗?在这种情况下,只传递键名是行不通的,你需要传递一个列表。如果您想按年龄降序排序,然后按姓名升序排序怎么办?现在对于每个字段名称,您还需要传递排序方向。这原则上是可以做到的。并且图书馆的作者可以走(但没有走这条路,而是选择了更通用和优雅的方式)。然后函数调用将如下所示:
在这里,我们传递了一个对列表
(имя-поля, направление-сортировки)(asc- 升序,desc- 降序)。但是这种方法存在问题:
为了解决这些问题,使用了这个技巧:不是比较元素本身,而是比较为元素计算的值。并获得这样的值(称为排序键 - 这就是为什么调用参数
key,不要与字典中的键混淆!)使用用户sorted传入参数的函数。也就是说,在排序算法内部,之前(对于数字算法)进行了比较:它会是这样的:
如您所见,对于我们正在排序的序列中的元素,我们调用函数(注意我们使用括号
key(el1)- 这意味着“调用存储在 key 变量中的函数并将 el1 变量中的值作为参数”),它在参数中传递key,并通过元素本身传递给它。这意味着该函数将能够从元素中“获取”值,该值已经用于比较。这是一种非常灵活的方式,因为它允许您根据情况比较任何元素(因为我们可能需要在不同情况下对相同的字典列表进行不同的排序,或者更改数字或字符串的排序顺序)。
例如,如果您需要按降序对数字进行排序,则使用以下函数:
如果我们想首先按年龄然后按名称对字典列表进行排序,那么以下函数将执行:
这里的键函数返回一个元组(元组),元组将被比较,对于它们,如您所知,比较的工作方式是较小的将是第一个组件较小的那个(在这里我们放那里的年龄),或者,如果第一个组件相同,则比较后者。结果,我们得到了我们需要的东西。
这是一个类比。在商品销售广告中,您可以说“商品价格为 100 美元”。并且可以写“可以通过电话查到商品的价格”。在第二种情况下,广告用户必须拨打电话获取价格(即调用函数获取价值)。我们只是给了他稍后获取值的机会(即函数本身
foo,而不是它计算的值)。