Python 中一些函数像 map、filter、any、all,还有 reduce、zip 和各种 itertools 函数,都属于处理列表或其他可迭代对象的工具。它们在函数式编程中很常见,能让代码更简洁。但在日常开发中,很少用到它们,可能是因为习惯了 for 循环或列表推导式。
先说说基础的几个:map、filter、any 和 all
这些是 Python 内置的,经常用于列表或其他序列的处理。
map 函数
map 的作用是把一个函数应用到列表的每个元素上,返回一个新的迭代器。
用法示例:
python
nums = [1, 2, 3]
squared = list(map(lambda x: x**2, nums)) # [1, 4, 9]
场景:批量转换数据,比如把数字平方或字符串转大写。
优势:代码简洁,底层高效。
用 for 循环的等价实现:
python
squared = []
for x in nums:
squared.append(x**2)
用列表推导式的等价实现:
python
squared = [x**2 for x in nums]
对比分析:map 更简洁,尤其是结合 lambda 时。但列表推导式更符合 Python 风格,可读性好。for 循环最直观,但代码多。map 的优势在大数据时(延迟计算,节省内存),劣势是需要转成 list 才能看到结果。为什么少用?很多人觉得列表推导式够用,不想多学一个函数。
filter 函数
filter 用一个条件函数筛选列表,只留满足条件的元素。
用法示例:
python
nums = [1, 2, 3, 4]
evens = list(filter(lambda x: x % 2 == 0, nums)) # [2, 4]
场景:数据过滤,比如提取偶数或非空字符串。
优势:简洁,延迟计算。
用 for 循环的等价实现:
python
evens = []
for x in nums:
if x % 2 == 0:
evens.append(x)
用列表推导式的等价实现:
python
evens = [x for x in nums if x % 2 == 0]
对比分析:filter 简短,但列表推导式更常见,可读性高。for 循环适合复杂条件。filter 的优势是函数式风格,劣势是初学者不熟。为什么少用?列表推导式太方便了,很多人直接用它。
any 函数
any 检查列表中是否有至少一个 True。
用法示例:
python
nums = [0, 0, 1]
has_true = any(nums) # True
场景:快速检查是否存在满足条件的元素,比如列表是否有负数。
优势:短路求值(一找到 True 就停),高效。
用 for 循环的等价实现:
python
has_true = False
for x in nums:
if x:
has_true = True
break
用列表推导式的等价实现:不太直接,通常结合 any 和生成器:
python
has_true = any(x for x in nums) # 但这和原函数一样
对比分析:any 最简洁,直观。for 循环显式,但代码长。列表推导式在这里不占优势。any 的劣势是需要生成器表达式。为什么少用?简单检查时,很多人直接写循环,不想用 any。
all 函数
all 检查列表中是否所有元素都是 True。
用法示例:
python
nums = [1, 2, 3]
all_true = all(nums) # True
场景:验证所有元素满足条件,比如所有成绩及格。
优势:短路求值,高效。
用 for 循环的等价实现:
python
all_true = True
for x in nums:
if not x:
all_true = False
break
用列表推导式的等价实现:类似 any,通常结合 all。
对比分析:all 简洁明了。for 循环可靠,但冗长。为什么少用?同 any,习惯问题。
再聊聊其他内置的:reduce、zip 和 sorted
这些也常用于迭代处理。
reduce 函数(需导入 functools)
reduce 把列表元素逐步累积计算成一个值。
用法示例:
python
from functools import reduce
nums = [1, 2, 3, 4]
total = reduce(lambda x, y: x + y, nums) # 10
场景:求和、乘积或合并数据。
优势:函数式,灵活。
用 for 循环的等价实现:
python
total = 0
for x in nums:
total += x
用列表推导式的等价实现:不适合累积,通常用 sum(nums) 代替简单求和。
对比分析:reduce 通用,但可读性差(尤其复杂函数)。for 循环清晰。reduce 的劣势是需导入,为什么少用?内置 sum/min/max 够用,reduce 显得多余。
zip 函数
zip 把多个列表配对成元组列表。
用法示例:
python
names = ['A', 'B']
scores = [90, 85]
pairs = list(zip(names, scores)) # [('A', 90), ('B', 85)]
场景:并行遍历多个序列。
优势:简洁,延迟计算。
用 for 循环的等价实现:
python
pairs = []
for i in range(min(len(names), len(scores))):
pairs.append((names[i], scores[i]))
用列表推导式的等价实现:
python
pairs = [(names[i], scores[i]) for i in range(min(len(names), len(scores)))]
对比分析:zip 最优雅。for 和推导式用索引,容易出错。zip 的劣势是长度不等时截断。为什么少用?初学者不熟,习惯用索引。
sorted 函数(带 key)
sorted 返回排序后的新列表,可自定义 key。
用法示例:
python
words = ['cat', 'dog', 'elephant']
sorted_words = sorted(words, key=len) # ['cat', 'dog', 'elephant']
场景:自定义排序。
优势:灵活,稳定。
用 for 循环的等价实现:不直接,需手动排序算法,如:
python
# 简单冒泡排序
sorted_words = words[:] # 复制
for i in range(len(sorted_words)):
for j in range(i+1, len(sorted_words)):
if len(sorted_words[i]) > len(sorted_words[j]):
sorted_words[i], sorted_words[j] = sorted_words[j], sorted_words[i]
用列表推导式的等价实现:不适合排序,通常用 sorted 本身。
对比分析:sorted 高效(内置算法)。手动 for 复杂、低效。为什么少用?简单排序不需 key,很多人直接 sorted(words)。
itertools 模块里的工具
itertools 有很多迭代工具,都返回迭代器。
chain 函数
chain 把多个列表连成一个。
用法示例:
python
from itertools import chain
list1 = [1, 2]
list2 = [3, 4]
combined = list(chain(list1, list2)) # [1, 2, 3, 4]
场景:合并数据源。
优势:高效,不复制。
用 for 循环的等价实现:
python
combined = []
for lst in [list1, list2]:
for x in lst:
combined.append(x)
用列表推导式的等价实现:
python
combined = [x for lst in [list1, list2] for x in lst]
对比分析:chain 简洁,内存好。for 和推导式直观。chain 的劣势是需导入。为什么少用?简单合并用 + 就行。
groupby 函数
groupby 把连续相同键的元素分组(需先排序)。
用法示例:
python
from itertools import groupby
words = sorted(['cat', 'dog', 'rat'], key=len)
groups = {k: list(g) for k, g in groupby(words, key=len)}
场景:数据分组。
优势:高效。
用 for 循环的等价实现:
python
groups = {}
current_key = None
for word in words:
key = len(word)
if key != current_key:
current_key = key
groups[key] = []
groups[key].append(word)
用列表推导式的等价实现:不太直接,需要类似 for 的逻辑。
对比分析:groupby 简洁,但需排序。for 灵活。为什么少用?分组场景少,很多人用 pandas。
combinations 和 permutations
combinations 生成组合,permutations 生成排列。
用法示例:
python
from itertools import combinations, permutations
items = ['A', 'B']
combs = list(combinations(items, 2)) # [('A', 'B')]
perms = list(permutations(items, 2)) # [('A', 'B'), ('B', 'A')]
场景:算法问题。
优势:高效。
用 for 循环的等价实现:嵌套循环,如 for combinations:
python
combs = []
for i in range(len(items)):
for j in range(i+1, len(items)):
combs.append((items[i], items[j]))
用列表推导式的等价实现:
python
combs = [(items[i], items[j]) for i in range(len(items)) for j in range(i+1, len(items))]
对比分析:itertools 简单。for/推导式易懂但代码长。为什么少用?排列组合不常见。
repeat 函数
repeat 重复生成值。
用法示例:
python
from itertools import repeat
list(repeat(42, 3)) # [42, 42, 42]
场景:填充常量。
优势:简单。
用 for 循环的等价实现:
python
vals = []
for _ in range(3):
vals.append(42)
用列表推导式的等价实现:
python
vals = [42 for _ in range(3)]
对比分析:repeat 短。推导式更常见。为什么少用?推导式太方便。
dropwhile 和 takewhile
dropwhile 丢弃开头直到条件假;takewhile 取开头直到条件假。
用法示例:
python
from itertools import dropwhile, takewhile
nums = [1,3,5,2,4]
list(dropwhile(lambda x: x % 2 != 0, nums)) # [2,4]
list(takewhile(lambda x: x % 2 != 0, nums)) # [1,3,5]
场景:切分序列。
优势:条件切片。
用 for 循环的等价实现:for dropwhile:
python
result = []
started = False
for x in nums:
if not started and x % 2 == 0:
started = True
if started:
result.append(x)
对比分析:itertools 简洁。for 显式。为什么少用?切分需求少。
zip_longest 函数
zip_longest 配对,填充短的。
用法示例:
python
from itertools import zip_longest
list(zip_longest([1,2], ['a','b','c'], fillvalue=0)) # [(1,'a'), (2,'b'), (0,'c')]
场景:不等长配对。
优势:处理缺失。
用 for 循环的等价实现:
python
result = []
max_len = max(len([1,2]), len(['a','b','c']))
for i in range(max_len):
a = [1,2][i] if i < len([1,2]) else 0
b = ['a','b','c'][i] if i < len(['a','b','c']) else 0
result.append((a, b))
对比分析:zip_longest 方便。for 繁琐。为什么少用?长度相等时用 zip。
starmap 函数
starmap 像 map,但解包元组。
用法示例:
python
from itertools import starmap
list(starmap(lambda x,y: x*y, [(2,3),(4,5)])) # [6,20]
场景:多参数映射。
优势:扩展 map。
用 for 循环的等价实现:
python
result = []
for pair in [(2,3),(4,5)]:
result.append(pair[0] * pair[1])
用列表推导式的等价实现:
python
result = [x*y for x,y in [(2,3),(4,5)]]
对比分析:starmap 函数式。推导式更直观。为什么少用?推导式够用。
结语
itertools中还有很多非常强大的函数,但更不常用了。虽然这些函数都是 Python 的好工具,能让代码更简洁高效,尤其大数据或函数式风格时。
为什么少用呢?我想一来是习惯吧:for 循环和列表推导式太接地气,可读性高。二是场景有限:很多函数针对特定问题,日常不遇。三是学习成本:需导入 itertools,觉得麻烦。