标准库篇
前两篇我们复习了输入输出和数据结构。今天来找找标准库里那些内置但容易被忽略的强大模块。
很多题目如果自己造轮子会非常繁琐,而标准库往往能一行代码解决问题。更重要的是,这些模块用C语言实现,速度远快于我们自己写的函数。
这一篇将重点介绍在竞赛中最常用、最实用的模块:itertools、functools、math、bisect,以及其他辅助库。掌握它们,你的代码将更加优雅,调试和编写效率也会大幅提升。
itertools:迭代器工具,暴力出奇迹
1. 排列与组合
蓝桥杯填空题和部分大题,数据规模小时可以直接枚举所有情况。
import itertools
# 全排列
for perm in itertools.permutations([1,2,3]): # 返回元组
print(perm)
# (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1)
# 组合(不考虑顺序)
for comb in itertools.combinations([1,2,3,4], 2):
print(comb)
# (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)
# 可重复组合(允许元素重复)
for comb in itertools.combinations_with_replacement([1,2,3], 2):
print(comb)
# (1,1), (1,2), (1,3), (2,2), (2,3), (3,3)
accumulate(iterable) # 前缀和
应用:暴力枚举所有可能的顺序或选择,适合数据量小的题目。
2. 笛卡尔积
for item in itertools.product([1,2], ['a','b']):
print(item)
# (1,'a'), (1,'b'), (2,'a'), (2,'b')
# 也可以指定重复次数
for item in itertools.product([0,1], repeat=3):
print(item) # 生成所有3位二进制数
应用:枚举所有状态组合,如开关灯问题。
3. 无限迭代器
# count(start, step) 无限递增
for i in itertools.count(10, 2):
if i > 20: break
print(i) # 10,12,14,16,18,20
# cycle(iterable) 无限循环
colors = itertools.cycle(['红','黄','蓝'])
for _ in range(7):
print(next(colors)) # 红黄蓝红黄蓝红
# repeat(object, times) 重复
for _ in itertools.repeat('hi', 3):
print(_) # hi hi hi
应用:轮询、重复操作、生成测试数据。
4. groupby:分组聚合
items = [('A',1), ('A',2), ('B',1), ('B',3)]
items.sort(key=lambda x: x[0]) # 必须先排序
for key, group in itertools.groupby(items, key=lambda x: x[0]):
print(key, list(group))
# A [('A',1), ('A',2)]
# B [('B',1), ('B',3)]
应用:统计连续相同元素、数据分组。
functools:函数工具,提升代码优雅度
1. lru_cache:记忆化递归
自动缓存是蓝桥杯动态规划(DP)的大杀器,可以替代手写DP数组。
from functools import lru_cache
@lru_cache(maxsize=None)
deffib(n):
if n < 2: return n
return fib(n-1) + fib(n-2)
print(fib(100)) # 瞬间出结果
特点:
- 默认参数不可哈希(如列表)会报错,可转成元组传入。
使用注意:递归深度大时仍需设置
sys.setrecursionlimit
2. partial:固定部分参数
from functools import partial
defpower(base, exp):
return base ** exp
square = partial(power, exp=2)
print(square(5)) # 25
应用:减少重复传参,例如在排序的 key 中固定函数。
3. reduce:累积运算
from functools import reduce
result = reduce(lambda x, y: x + y, [1,2,3,4]) # 10
# 相当于 (((1+2)+3)+4)
应用:求积、拼接、按规则累积。Python 3 中 reduce 被移入 functools,不再是内置。
math:数学计算
1. 常用函数
import math
math.gcd(a, b) # 最大公约数
math.factorial(n) # 阶乘
math.sqrt(x) # 平方根
math.pow(x, y) # x**y 浮点数
math.comb(n, k) # 组合数 C(n,k)
math.perm(n, k) # 排列数 P(n,k)
math.isqrt(n) # 整数平方根(向下取整)
2. 浮点数处理
- 取整:
math.floor, math.ceil, math.trunc
应用:数论题(gcd、质数判断)、几何题(距离、角度)。
3. 快速幂
Python 内置 pow(base, exp, mod) 可以高效计算 base**exp % mod,支持大指数。
pow(2, 10**9, 1000000007) # 快速幂取模
bisect:二分查找告别手写
import bisect
arr = [1, 3, 5, 7]
pos = bisect.bisect_left(arr, 4) # 返回插入位置,保持有序,2
pos = bisect.bisect_right(arr, 5) # 返回插入位置(右侧),3
bisect.insort_left(arr, 4) # 插入并保持有序
应用:
- 配合
list 维护动态有序集合(但插入是 O(n),若频繁插入可用 bisect+list 或 sortedcontainers 第三方库,但竞赛中一般只允许标准库)。 - 经典用法:最长递增子序列的 O(n log n) 解法。
其他实用模块
string —— 字符串常量
| |
|---|
ascii_letters | 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
ascii_lowercase | |
ascii_uppercase | |
digits | '0123456789' |
hexdigits | |
punctuation | |
使用场景:生成测试数据、字符映射等。
calendar:日期计算
import calendar
calendar.isleap(2024) # 闰年判断 True
calendar.weekday(2024, 3, 21) # 返回星期几(0=周一)
应用:日期模拟、星期计算,避免手动计算闰年。
random:随机数
import random
random.randint(1, 10) # 整数
random.random() # [0.0,1.0) 浮点数
random.choice([1,2,3]) # 随机选一个
random.shuffle(arr) # 打乱列表
注意:竞赛中一般不用随机化算法,但可用于生成测试数据。
time:计时(本地调优)
import time
start = time.time()
# ... 代码 ...
print(time.time() - start)
注意:不要在最终提交代码中包含计时语句。
datetime —— 日期时间
| |
|---|
date(year, month, day) | |
timedelta(days=n) | |
weekday() | |
strftime() | |
易错点:date对象可以直接比较大小、相减得到timedelta。
from datetime import date, timedelta
d1 = date(2023, 4, 1)
d2 = date(2023, 4, 10)
delta = d2 - d1 # timedelta(days=9)
print(d1.weekday()) # 5(星期六,周一=0)
常见坑点与技巧
1. itertools 返回迭代器,若需多次使用请转为列表
perms = list(itertools.permutations(arr))
2. lru_cache 的参数必须是可哈希的
@lru_cache(maxsize=None)
defdfs(state, idx):
# state 如果是列表,会报错
# 可以转为元组 dfs(tuple(state), idx)
3. bisect 只对有序序列有效,插入后记得保持有序
bisect.insort_left(lst, x) # 保持有序
4. math.gcd 可处理负数,返回非负结果
math.gcd(-4, 6) # 2
5. pow 取模适用于大指数,比 ** 后取模快得多
小结
标准库是Python竞赛的合法外挂。掌握它们,你就能用更少的代码实现更复杂的功能,同时获得更高的运行效率。
| |
|---|
itertools | |
functools | |
math | |
bisect | |
calendar | |
string | |