理解给定Python代码中的lambda用法
在阅读一些代码时,我遇到了下面这段代码,我看不太懂。有没有人能给我一些指导、提示、链接或者对下面第3行的基本解释呢?
def do_store(*args, **kwargs):
try:
key = (args, tuple(sorted(kwargs.items(), key=lambda i:i[0])))
results = f._results
主要是,下面这段代码在做什么呢?
key=lambda i:i[0]
5 个回答
Lambda 是一种让你可以用简单的表达式来创建匿名函数的工具。这里的匿名函数接受一个参数 'i',并返回 'i' 中索引为零的元素。
在这个例子中,它的作用是创建一个函数,用来选择一个排序的关键字,以便被 'sorted()' 函数使用。
如果不提到第二个参数 , key=lambda i:i[0]
,那么字典里的内容(kwargs)就会按照它们的完整名称进行排序。举个例子,在下面这个调用中:
do_store(abc=1, xyz=2, nji=3)
kwargs 是一个字典 {abc: 1, xyz: 2, nji: 3},使用 sorted(kwargs.items())
进行排序的结果会是 [('abc', 1), ('nji', 3), ('xyz', 2)]
。这里默认的排序方式是 lambda i: i
,也就是说,对于字典里的每一个元素,我们直接用这个元素本身来进行比较。在你的例子中,我们只会使用每个项的第一个部分进行排序,也就是字典的键,因为每个项都是一个键值对(key, value)。
有三种等价的写法:
sorted(kwargs.items(), key=lambda i:i[0])
(这就是你现在用的那种)
def first_item(aList): return aList[0]
sorted(kwargs.items(), key=first_item)
from operator import itemgetter
sorted(kwargs.items(), key=itemgetter(0))
在所有情况下,参数 key
都是传入一个函数,这个函数接收一个参数并返回这个参数的第一个元素。
这里的 lambda 是一种简写方式,不需要给这个函数起名字。给函数起名字可能会帮助阅读代码的人,特别是当表达式比较复杂的时候。itemgetter
函数在速度上有一点优势,但它的灵活性不如前面提到的方式,因为它只能返回一个或多个项目;如果你想对这些项目进行进一步处理(比如把它们变成小写),你就得用 def
或 lambda
。
其他回答已经很好地解释了 lambda
和 sorted
的 key
参数的作用。简单来说:
key
用来提供一个比较的关键函数,我们称之为 f,这样如果 f(x) < f(y),那么在排序后的列表中 x 会出现在 y 之前。lambda
可以快速简洁地创建这样的函数,而不需要专门写一个def
只为这一次排序;你也可以使用其他任何函数(自己定义的、内置的等等)。
不过,关于 key=lambda i:i[0]
在你的代码中做了什么:实际上,它什么也没做!
更准确地说,它告诉 sorted
按照要排序的列表中元组的第一个元素进行排序,这个列表是通过 kwargs.items()
生成的,也就是一系列 (key, value)
的元组。但实际上,元组的默认排序就是按第一个元素排序,如果第一个元素相同,才会按第二个元素排序,依此类推。不过,由于这些元组是字典的 (keys, values)
,所以没有两个元组的第一个元素是相同的,因此使用这个特定的关键函数和默认排序是完全一样的。
你也可以使用 key = (args, tuple(sorted(kwargs.items())))
。
如果你在问 为什么 会这样做:这个函数似乎是用来进行 记忆化,将函数参数(存储在 args
和 kwargs
中)映射到之前计算的值。为此,kwargs
字典必须转换为元组,因为字典是不可哈希的,也就是说不能用作另一个字典的键。为了确保相同的字典总是能得到相同的元组,它必须被排序,因为字典是无序的。
使用 lambda
这个关键词,你可以创建“匿名函数”。这些函数不需要名字,因为它们通常会立即被赋值给一个回调函数。
lambda i:i[0]
这只是函数的主体部分
def f(i):
return i[0]
sorted
函数的 key
参数需要是一个可以计算给定项目排序关键字的函数。你可以传递上面定义的函数名 f
,或者使用 lambda
函数,这样代码会更易读。
正如 tobias_k 的回答中提到的,这段代码中的 key
参数其实是没用的。