Python 中那些鲜为人知但实用的工具函数

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,觉得麻烦。

相关推荐
weixin_421133413 小时前
Django 的文档接口
python·django·sqlite
LK_073 小时前
【Open3D】Ch.3:顶点法向量估计 | Python
开发语言·笔记·python
小码哥0683 小时前
智能化招聘系统设计与实现-Java
开发语言·python
饮浊酒3 小时前
Python学习-----小游戏之人生重开模拟器(普通版)
python·学习·游戏程序
CryptoRzz4 小时前
越南k线历史数据、IPO新股股票数据接口文档
java·数据库·后端·python·区块链
chenchihwen4 小时前
深度解析RAG系统中的PDF解析模块:Docling集成与并行处理实践
python·算法·pdf
MasonYyp4 小时前
简单使用Marker
python·语言模型
std860214 小时前
使用 python-docx 和 difflib 对比 Word 文档
python
java1234_小锋5 小时前
TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 使用Keras实现分类问题
python·深度学习·tensorflow·tensorflow2