理解给定Python代码中的lambda用法

9 投票
5 回答
1004 浏览
提问于 2025-04-18 11:33

在阅读一些代码时,我遇到了下面这段代码,我看不太懂。有没有人能给我一些指导、提示、链接或者对下面第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 个回答

1

Lambda 是一种让你可以用简单的表达式来创建匿名函数的工具。这里的匿名函数接受一个参数 'i',并返回 'i' 中索引为零的元素。

在这个例子中,它的作用是创建一个函数,用来选择一个排序的关键字,以便被 'sorted()' 函数使用。

4

如果不提到第二个参数 , 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)。

7

有三种等价的写法:

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 函数在速度上有一点优势,但它的灵活性不如前面提到的方式,因为它只能返回一个或多个项目;如果你想对这些项目进行进一步处理(比如把它们变成小写),你就得用 deflambda

9

其他回答已经很好地解释了 lambdasortedkey 参数的作用。简单来说:

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

如果你在问 为什么 会这样做:这个函数似乎是用来进行 记忆化,将函数参数(存储在 argskwargs 中)映射到之前计算的值。为此,kwargs 字典必须转换为元组,因为字典是不可哈希的,也就是说不能用作另一个字典的键。为了确保相同的字典总是能得到相同的元组,它必须被排序,因为字典是无序的。

12

使用 lambda 这个关键词,你可以创建“匿名函数”。这些函数不需要名字,因为它们通常会立即被赋值给一个回调函数。

lambda i:i[0]

这只是函数的主体部分

def f(i):
  return i[0]

sorted 函数的 key 参数需要是一个可以计算给定项目排序关键字的函数。你可以传递上面定义的函数名 f,或者使用 lambda 函数,这样代码会更易读。

正如 tobias_k 的回答中提到的,这段代码中的 key 参数其实是没用的。

撰写回答