飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 第1章 Python简介

    • Python是什么
    • 安装与运行
    • 交互式解释器
    • 注释与编码规范
  • 第2章 变量与数据类型

    • 变量与对象
    • 整数 int
    • 浮点数 float
    • 复数 complex
    • 布尔值 bool
    • 字符串 str
    • 空值 None
    • 类型转换
  • 第3章 运算符与表达式

    • 算术运算符
    • 比较运算符
    • 赋值运算符
    • 逻辑运算符
    • 位运算符
    • 身份与成员运算符
    • 海象运算符
    • 运算符优先级
  • 第4章 流程控制

    • if 语句
    • if-else 语句
    • if-elif-else 语句
    • match-case 语句
    • 条件表达式(三元运算符)
    • while 循环
    • for 循环
    • range 函数
    • break 与 continue
    • 循环的 else 子句
    • pass 语句
  • 第5章 数据结构

    • 列表创建与索引
    • 列表方法
    • 列表推导式
    • 元组
    • 序列解包
    • 集合
    • 字典创建与访问
    • 字典方法
    • 字典推导式
    • range 对象
  • 第6章 函数

    • 定义函数
    • 位置参数与关键字参数
    • 默认参数
    • 可变参数
    • 解包实参
    • 函数返回值
    • lambda 表达式
    • 文档字符串与注解
    • 作用域与命名空间
    • global 与 nonlocal
  • 第7章 模块与包

    • 模块导入
    • 模块搜索路径
    • 包与相对导入
    • 标准库概览
  • 第8章 文件与输入输出

    • 文件读写
    • 上下文管理器
    • 字符串格式化
    • JSON 与 CSV
  • 第9章 面向对象

    • 类与对象
    • 方法
    • 实例变量与类变量
    • 私有变量
    • 继承
    • 多重继承
    • 魔术方法
    • 属性装饰器
    • 数据类 dataclass
  • 第10章 异常处理

    • 语法错误与异常
    • try-except
    • 异常链与 raise
    • 清理操作
    • 自定义异常
  • 第11章 迭代器与生成器

    • 迭代器协议
    • 生成器
    • 生成器表达式
    • 迭代工具
  • 第12章 高级特性

    • 装饰器
    • 函数式编程
  • 第13章 工程实践

    • 测试与调试
    • 代码质量
    • 虚拟环境

lambda 表达式

lambda 关键字用于创建匿名函数——没有名称、只能包含单个表达式的小型函数。它在语法上是 def 语句的受限版本,但在语义上等价于一个嵌套函数定义。lambda 的设计初衷是提供一种简洁的、内联的函数书写方式,用于那些"只使用一次"的简单场景。

lambda 的基本语法

lambda 表达式的语法为 lambda 参数: 表达式。参数列表与普通函数相同(支持默认参数、*args、**kwargs),但冒号后只能有一个表达式,不能包含语句:

# 普通函数
def add(x, y):
    return x + y

# 等价的 lambda
add_lambda = lambda x, y: x + y

print(add(2, 3))          # 5
print(add_lambda(2, 3))   # 5

lambda 表达式本身求值为一个函数对象,因此可以立即调用:

print((lambda x: x * x)(5))   # 25

lambda 的限制

lambda 比普通函数严格得多,只能包含一个表达式,不能包含以下任何内容:

  • 多条语句
  • 赋值语句(=)
  • return、yield、pass、assert
  • raise(虽然某些情况下可以,但不推荐)
  • 类型注解
  • 文档字符串
# 非法:lambda 不能包含赋值
# lambda x: y = x + 1; return y

# 非法:lambda 不能包含多条语句
# lambda x: print(x); x + 1

# 合法:表达式可以调用函数
lambda x: print(x) or x + 1   # 利用 or 的短路特性,但可读性差

如果需要复杂逻辑,应该使用 def 定义命名函数。lambda 的价值在于简洁,一旦变得晦涩,就失去了意义。

lambda 与 def 的本质区别

从语义上看,lambda 和 def 创建的函数对象几乎相同,但有几点差异:

  1. 名称:lambda 函数对象的 __name__ 属性固定为 <lambda>,不利于调试:
f = lambda x: x + 1
print(f.__name__)   # '<lambda>'

def g(x):
    return x + 1
print(g.__name__)   # 'g'
  1. 作用域:两者都遵循相同的 LEGB 规则,都可以引用外层变量形成闭包。

  2. 语法位置:lambda 是表达式,可以出现在任何需要值的地方;def 是语句,只能出现在语句位置。

排序中的使用

lambda 最常见的用途之一是为 sorted() 和 list.sort() 提供 key 函数:

students = [
    ("Alice", 85),
    ("Bob", 92),
    ("Charlie", 78),
]

# 按分数(第二个元素)排序
by_score = sorted(students, key=lambda s: s[1])
print(by_score)
# [('Charlie', 78), ('Alice', 85), ('Bob', 92)]

# 按分数降序
by_score_desc = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score_desc)
# [('Bob', 92), ('Alice', 85), ('Charlie', 78)]

对于更复杂的排序规则,lambda 可以返回元组实现多级排序:

# 先按分数降序,分数相同按名字升序
students = [("Alice", 85), ("Bob", 92), ("Charlie", 85)]
result = sorted(students, key=lambda s: (-s[1], s[0]))
print(result)
# [('Bob', 92), ('Alice', 85), ('Charlie', 85)]

映射与过滤

lambda 也常与 map()、filter() 配合使用:

nums = [1, 2, 3, 4, 5]

# 映射:每个元素平方
squares = list(map(lambda x: x ** 2, nums))
print(squares)   # [1, 4, 9, 16, 25]

# 过滤:保留偶数
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)     # [2, 4]

不过,现代 Python 更推荐使用列表推导式,通常比 map/filter 加 lambda 更易读:

# 列表推导式等价写法
squares = [x ** 2 for x in nums]
evens = [x for x in nums if x % 2 == 0]

闭包中的 lambda

lambda 可以引用包含作用域中的变量,形成闭包:

def make_multiplier(n):
    return lambda x: x * n

double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))   # 10
print(triple(5))    # 15

但这里有一个经典陷阱:在循环中创建 lambda 时,所有 lambda 共享同一个变量引用:

# 错误示范
funcs = []
for i in range(3):
    funcs.append(lambda: i)

print(funcs[0]())   # 2,不是 0!
print(funcs[1]())   # 2,不是 1!
print(funcs[2]())   # 2

原因是 lambda 捕获的是变量 i 的引用,而不是当时的值。循环结束时 i 为 2,所以所有 lambda 都返回 2。修复方法是利用默认参数在定义时求值的特性:

# 正确做法
funcs = []
for i in range(3):
    funcs.append(lambda x=i: x)   # 默认参数在定义时绑定当前值

print(funcs[0]())   # 0
print(funcs[1]())   # 1
print(funcs[2]())   # 2

常见错误

试图在 lambda 中写多条语句:

# lambda x: x += 1; return x   # SyntaxError

过度使用 lambda 导致可读性下降:

# 不推荐:复杂的 lambda 难以阅读
process = lambda data: [x.strip().lower() for x in data if x and len(x) > 3]

# 推荐:用 def 命名,语义清晰
def process(data):
    return [x.strip().lower() for x in data if x and len(x) > 3]

小结

lambda 是创建小型匿名函数的语法糖,只能包含单个表达式,没有名称和文档字符串。它适合排序 key、简单映射等一次性场景。一旦逻辑复杂,应改用 def。理解 lambda 与 def 的等价性,以及闭包中的变量捕获陷阱,才能正确使用这个工具。

上一页
函数返回值
下一页
文档字符串与注解