16 - 常用内置函数与标准库
16 - 常用内置函数与标准库
Python 自带了很多好用的函数和模块,这章挑最实用的讲。不用全记住,知道有这些东西,需要的时候回来查就行。
常用内置函数
数学相关
# abs() — 绝对值print(abs(-5))# 5# round() — 四舍五入print(round(3.7))# 4print(round(3.14159,2))# 3.14# max() / min() — 最大值/最小值print(max(3,1,4,1,5))# 5print(min([3,1,4]))# 1# sum() — 求和print(sum([1,2,3,4,5]))# 15print(sum([1,2,3],10))# 16(10 是起始值)# pow() — 幂运算print(pow(2,10))# 1024print(pow(2,10,100))# 24(2^10 % 100)# divmod() — 同时得到商和余数q,r=divmod(17,5)print(q,r)# 3 2类型转换
int("42")# 字符串转整数float("3.14")# 字符串转浮点数str(42)# 数字转字符串bool(0)# 转布尔值list("abc")# ['a', 'b', 'c']tuple([1,2,3])# (1, 2, 3)set([1,1,2])# {1, 2}dict(a=1,b=2)# {'a': 1, 'b': 2}序列操作
# len() — 长度print(len([1,2,3]))# 3print(len("hello"))# 5# sorted() — 排序(返回新列表)print(sorted([3,1,4,1,5]))# [1, 1, 3, 4, 5]print(sorted("python"))# ['h', 'n', 'o', 'p', 't', 'y']# 自定义排序words=["banana","apple","cherry"]print(sorted(words,key=len))# ['apple', 'banana', 'cherry']# reversed() — 反转(返回迭代器)print(list(reversed([1,2,3])))# [3, 2, 1]# range() — 数字序列print(list(range(5)))# [0, 1, 2, 3, 4]print(list(range(1,10,2)))# [1, 3, 5, 7, 9]map、filter、zip
# map() — 对每个元素应用函数numbers=[1,2,3,4,5]squares=list(map(lambdax:x**2,numbers))print(squares)# [1, 4, 9, 16, 25]# 等价的列表推导式(更推荐)squares=[x**2forxinnumbers]# filter() — 过滤元素evens=list(filter(lambdax:x%2==0,numbers))print(evens)# [2, 4]# 等价的列表推导式evens=[xforxinnumbersifx%2==0]# zip() — 配对names=["小明","小红"]ages=[25,22]print(list(zip(names,ages)))# [('小明', 25), ('小红', 22)]# zip 创建字典d=dict(zip(names,ages))print(d)# {'小明': 25, '小红': 22}map和filter在 Python 里用得没有 JavaScript 那么多,因为列表推导式通常更清晰。但认识它们很重要,读别人的代码时会遇到。
any 和 all
# any() — 有一个 True 就是 Trueprint(any([False,False,True]))# Trueprint(any([0,"",None]))# False# all() — 全部 True 才是 Trueprint(all([True,True,True]))# Trueprint(all([True,False,True]))# Falseprint(all([]))# True(空序列返回 True)# 实际用法numbers=[2,4,6,8]print(all(n%2==0forninnumbers))# True(全是偶数)words=["hello","world","python"]print(any(len(w)>5forwinwords))# True(有长度超过5的)enumerate
fruits=["苹果","香蕉","橘子"]fori,fruitinenumerate(fruits):print(f"{i}:{fruit}")# 指定起始索引fori,fruitinenumerate(fruits,start=1):print(f"第{i}个:{fruit}")常用标准库
os — 操作系统交互
importos# 当前工作目录print(os.getcwd())# 环境变量print(os.environ.get("HOME"))print(os.getenv("PATH","未设置"))# 执行系统命令(不推荐用 os.system,用 subprocess)importsubprocess result=subprocess.run(["ls","-l"],capture_output=True,text=True)print(result.stdout)sys — 系统相关
importsysprint(sys.version)# Python 版本print(sys.platform)# 平台(linux/darwin/win32)print(sys.argv)# 命令行参数print(sys.path)# 模块搜索路径# 退出程序# sys.exit(0) # 正常退出# sys.exit(1) # 异常退出datetime — 日期时间
fromdatetimeimportdatetime,date,timedelta# 当前时间now=datetime.now()print(now)# 2024-05-25 14:30:00.123456print(now.strftime("%Y-%m-%d %H:%M:%S"))# 格式化# 创建指定时间dt=datetime(2024,1,15,10,30)# 时间差tomorrow=now+timedelta(days=1)last_week=now-timedelta(weeks=1)# 时间比较print(tomorrow>now)# True# 解析字符串dt=datetime.strptime("2024-05-25","%Y-%m-%d")# 只用日期today=date.today()print(today)# 2024-05-25random — 随机数
importrandom# 随机整数print(random.randint(1,100))# 随机浮点数print(random.random())# 0-1 之间print(random.uniform(1,10))# 1-10 之间# 随机选择fruits=["苹果","香蕉","橘子"]print(random.choice(fruits))# 随机选一个print(random.sample(fruits,2))# 随机选两个(不重复)# 打乱顺序numbers=[1,2,3,4,5]random.shuffle(numbers)print(numbers)# 比如 [3, 1, 5, 2, 4]collections — 高效数据结构
前面已经讲过defaultdict和Counter,这里补充几个:
fromcollectionsimportdeque,OrderedDict# deque — 双端队列(两头都能快速增删)d=deque([1,2,3])d.appendleft(0)# 左边加d.append(4)# 右边加d.popleft()# 左边删print(d)# deque([1, 2, 3, 4])# 限制最大长度(滑动窗口)d=deque(maxlen=3)d.append(1)d.append(2)d.append(3)d.append(4)# 1 被自动挤掉print(d)# deque([2, 3, 4], maxlen=3)# OrderedDict — 有序字典(Python 3.7+ 普通 dict 也有序了,用得少了)itertools — 迭代器工具
fromitertoolsimportchain,product,combinations,groupby# chain — 把多个可迭代对象连起来forxinchain([1,2],[3,4],[5]):print(x)# 1 2 3 4 5# product — 笛卡尔积forx,yinproduct("AB","12"):print(x,y)# A1 A2 B1 B2# combinations — 组合forcomboincombinations("ABCD",2):print(combo)# ('A','B') ('A','C') ('A','D') ('B','C') ('B','D') ('C','D')# groupby — 分组(数据需要先排序)data=[("A班","小明"),("A班","小红"),("B班","小刚")]data.sort(key=lambdax:x[0])# 必须先排序forkey,groupingroupby(data,key=lambdax:x[0]):print(f"{key}:{list(group)}")functools — 函数工具
fromfunctoolsimportreduce,lru_cache# reduce — 累积计算fromfunctoolsimportreduceresult=reduce(lambdaa,b:a+b,[1,2,3,4,5])print(result)# 15(((((1+2)+3)+4)+5))# lru_cache — 函数缓存(缓存装饰器)@lru_cache(maxsize=128)deffibonacci(n):ifn<2:returnnreturnfibonacci(n-1)+fibonacci(n-2)print(fibonacci(100))# 瞬间算出来,没缓存的话会慢得要死@lru_cache是个很实用的装饰器,能缓存函数的计算结果。对于递归或者重复计算的场景,性能提升巨大。
pathlib — 路径处理
第 12 章已经讲过了,这里简单回顾:
frompathlibimportPath p=Path("data")/"output"/"result.txt"p.parent.mkdir(parents=True,exist_ok=True)p.write_text("hello",encoding="utf-8")content=p.read_text(encoding="utf-8")本章小结
map/filter配合 lambda 做数据变换,但列表推导式通常更清晰any/all做批量条件判断sorted+key参数可以自定义排序规则datetime处理日期时间,timedelta做时间差计算collections里的deque、Counter、defaultdict很实用functools.lru_cache一行代码就能给函数加缓存
面试题
Q1:map()和列表推导式有什么区别?哪个更推荐?
功能上等价,都能对序列中每个元素做变换:
# maplist(map(lambdax:x**2,[1,2,3]))# 列表推导式[x**2forxin[1,2,3]]区别:
- 可读性:简单变换用 map 还行,复杂的逻辑列表推导式更清晰
- 灵活性:列表推导式可以加
if过滤,map 不行(需要配合 filter) - 性能:差别很小,不需要纠结
Python 社区更推荐列表推导式(Pythonic),除非已有现成函数(如map(str, numbers))。
Q2:@lru_cache是怎么工作的?什么场景适合用?
@lru_cache用 LRU(Least Recently Used)算法缓存函数的返回值。参数相同时直接返回缓存结果,不重新计算。
适合场景:
- 递归(如 Fibonacci),避免重复计算
- 重复查询(如配置读取、API 调用)
- 纯函数(同样的输入总是同样的输出)
不适合:有副作用的函数(如写文件、修改全局变量),因为第二次调用不会真正执行。
maxsize控制缓存大小,None表示不限制。
Q3:datetime中timedelta的用途是什么?
timedelta表示两个时间点之间的时间差,可以做日期时间的加减运算:
fromdatetimeimportdatetime,timedelta now=datetime.now()tomorrow=now+timedelta(days=1)two_hours_later=now+timedelta(hours=2)last_week=now-timedelta(weeks=1)# 两个 datetime 相减得到 timedeltadiff=datetime(2024,12,31)-datetime(2024,1,1)print(diff.days)# 365支持 days、seconds、microseconds、milliseconds、minutes、hours、weeks 参数。
Q4:deque和list有什么区别?什么时候用 deque?
| 操作 | list | deque |
|---|---|---|
| 末尾增删 | O(1) | O(1) |
| 头部增删 | O(n) | O(1) |
| 中间增删 | O(n) | O(n) |
| 随机访问 | O(1) | O(n) |
list 在头部插入/删除是 O(n)(所有元素后移),deque 是 O(1)。
用 deque 的场景:
- 需要在两端操作(如队列、双端队列)
- 需要限制最大长度(
deque(maxlen=N)实现滑动窗口)
用 list 的场景:
- 需要随机访问(
lst[i]) - 主要在末尾操作
