欢迎来到 Python 学习计划的第 29 天!🎉
前几天我们学习了 lambda 匿名函数 和 条件表达式,今天我们要进入 Python 函数式编程的核心工具之一——map() 函数。
map() 是一个非常强大的高阶函数,它能让你无需编写显式的 for 循环,就能对序列中的每个元素进行处理。
一、什么是 map() 函数?
1. 定义
map() 函数会根据提供的函数,对指定的**可迭代对象(Iterable)**中的每一个元素进行处理,并返回一个包含处理结果的新迭代器。
简单来说:“映射” = “把一个函数应用到一堆数据上”。
2. 基本语法
map(function, iterable, ...)
- function:要应用的函数(可以是内置函数、自定义函数或 lambda)。
- iterable:一个或多个可迭代对象(如列表、元组、字符串)。
- 返回值:一个 迭代器(iterator)(Python 3 中)。
⚠️ 注意:在 Python 3 中,map() 返回的是迭代器,不会立即计算结果。如果需要查看结果,通常需要用 list() 转换。二、基础使用示例
1. 使用内置函数
将列表中的每个数字转换为字符串。
numbers = [1, 2, 3, 4, 5]# 使用 map 将每个数字转为字符串str_numbers = map(str, numbers)print(list(str_numbers)) # ['1', '2', '3', '4', '5']
2. 使用自定义函数
计算列表中每个数字的平方。
def square(x): return x ** 2numbers = [1, 2, 3, 4, 5]squared = map(square, numbers)print(list(squared)) # [1, 4, 9, 16, 25]
3. 使用 lambda 函数(最常见)
结合之前学的 lambda,代码更简洁。
numbers = [1, 2, 3, 4, 5]# lambda 直接定义逻辑squared = map(lambda x: x ** 2, numbers)print(list(squared)) # [1, 4, 9, 16, 25]
三、高级用法:多个可迭代对象
map() 可以接收多个可迭代对象,函数必须接收相应数量的参数。它会并行地从每个 iterable 中取一个元素传给函数。
示例:两个列表对应元素相加
list1 = [1, 2, 3]list2 = [10, 20, 30]# 函数接收两个参数added = map(lambda x, y: x + y, list1, list2)print(list(added)) # [11, 22, 33]
示例:长度不一致时
当其中一个 iterable 耗尽时,map() 停止。
list1 = [1, 2, 3, 4]list2 = [10, 20]# 只处理到最短的那个列表结束added = map(lambda x, y: x + y, list1, list2)print(list(added)) # [11, 22] (3 和 4 被忽略)
四、map() vs 列表推导式
在 Python 中,列表推导式(List Comprehension) 通常被认为是更 "Pythonic" 的写法。那么什么时候用 map(),什么时候用列表推导式?
1. 功能对比
numbers = [1, 2, 3, 4, 5]# 使用 mapsquared_map = list(map(lambda x: x ** 2, numbers))# 使用列表推导式squared_comp = [x ** 2 for x in numbers]print(squared_map == squared_comp) # True
2. 选择建议
场景 | 推荐写法 | 原因 |
|---|
简单转换 | 列表推导式 | 可读性更高,更符合 Python 习惯 |
已有函数 | map()
| 如果函数已定义(如 str, int),map 更简洁 |
复杂逻辑 | 列表推导式 | lambda 不适合复杂逻辑,推导式更清晰 |
内存优化 | map()
| map 返回迭代器,惰性计算,省内存
|
示例:已有函数的情况
strings = ['1', '2', '3']# ✅ 推荐:map 更简洁ints = list(map(int, strings))# ❌ 不推荐:推导式略显冗余ints = [int(s) for s in strings]
五、map() 的特性与陷阱
1. 惰性计算(Lazy Evaluation)
map() 返回的是迭代器,只有在遍历时才计算。这对于处理大数据非常有利。
# 不会立即计算,不会占用大量内存large_map = map(lambda x: x * 2, range(1000000))# 只取前 5 个结果for i, val in enumerate(large_map): if i >= 5: break print(val)
2. 只能遍历一次
迭代器一旦耗尽,就不能再次使用。
numbers = [1, 2, 3]result = map(lambda x: x * 2, numbers)print(list(result)) # [2, 4, 6]print(list(result)) # [] (❌ 第二次为空,因为已耗尽)
3. 函数为 None 的情况
如果第一个参数是 None,map 会Identity 函数处理(即返回元素本身),通常用于合并多个 iterable。
# Python 3 中不支持 function 为 None,会报错# map(None, [1, 2], [3, 4]) # ❌ TypeError
⚠️ 注意:function=None 的特性在 Python 2 中存在,但在 Python 3 中已移除。六、最佳实践
✅ 推荐做法
- 配合内置函数:如
map(int, list),map(str, list)。 - 大数据处理:利用其迭代器特性,节省内存。
- 已有函数复用:如果逻辑已封装在函数中,直接用
map。
❌ 避免做法
- 复杂 lambda:不要在
map 里写复杂的 lambda 逻辑,改用列表推导式或普通循环。 - 多次遍历:如果需要多次使用结果,请先转换为
list。 - 副作用操作:不要用
map 执行打印等操作(如 map(print, list)),虽然可行但不优雅。
七、实战练习
练习 :字符串清洗
有一个包含空格的字符串列表 words = [' hello ', ' world ', ' python '],请使用 map() 去除每个字符串的首尾空格。
words = [' hello ', ' world ', ' python ']# 使用内置方法 stripcleaned = list(map(str.strip, words))print(cleaned) # ['hello', 'world', 'python']
八、总结
特性 | 说明 |
|---|
功能 | 将函数应用到可迭代对象的每个元素 |
语法 | map(func, iterable, ...)
|
返回值 | 迭代器(Python 3),需用 list() 查看 |
多参数 | 支持多个 iterable,函数需对应多参数 |
对比 | 简单转换推荐列表推导式,内置函数推荐 map |
内存 | 惰性计算,适合大数据流 |
📌 明日预告:
明天我们将学习函数式编程三剑客的另外一位——filter() 函数。它将教会你如何根据条件筛选数据。之后我们将正式进入 面向对象编程(OOP) 的篇章!
掌握 map(),让你的数据处理更高效!继续加油!🚀