1. 为什么我要把77个Python函数翻出来重新整理
刚学Python那会儿,我特别迷信“背函数”。网上搜“Python常用函数”,收藏了几十篇,结果真到写代码的时候,脑子里只剩一个print()。后来带新人、做Code Review、帮同事排查脚本问题,我才慢慢意识到:函数不是拿来背的,是拿来“认脸”的。你不需要记住每个参数的默认值,但你必须知道“这个场景大概有哪个函数能干活”,然后去查文档、去试。
这篇总结的77个函数,是我从日常写脚本、做数据处理、搭小工具的过程中,反复用到、反复查、反复教别人的那一批。它们覆盖了内置函数、字符串处理、列表字典操作、文件读写、异常处理、常用标准库这几个高频区域。我不会给你一个干巴巴的清单,而是按“这个函数解决什么问题、什么时候用、有什么坑”来讲。适合刚入门Python、能写简单脚本但总觉得“不够顺手”的人,也适合工作几年但想系统梳理一下基础工具链的开发者。
提示:函数签名和参数细节以你当前使用的Python版本官方文档为准,本文侧重使用场景和实操经验。
2. 内置函数:那些你每天都在用但可能没用透的家伙
2.1 类型转换与判断:int、float、str、bool、type、isinstance
int()、float()、str()、bool()这四个是类型转换的“四大金刚”。但很多人不知道int()可以带第二个参数做进制转换:
int('ff', 16) # 255 int('1010', 2) # 10这个在解析配置文件、处理硬件返回的十六进制数据时特别有用。bool()的坑在于:空字符串、空列表、空字典、None、数字0都会返回False,其他返回True。我见过有人写if bool(user_input):来判断用户是否输入了内容,其实直接if user_input:就够了。
type()和isinstance()的区别是面试常问的。type(obj) == int不会考虑继承关系,而isinstance(obj, int)会。实际开发中优先用isinstance(),因为你的代码可能用到子类或者bool(bool是int的子类)。
isinstance(True, int) # True type(True) == int # False2.2 数学运算:abs、round、pow、divmod、sum、min、max
abs()取绝对值,round()四舍五入。注意round()的“银行家舍入”行为:
round(2.5) # 2 round(3.5) # 4它不是简单的四舍五入,而是“四舍六入五成双”。做金融计算时千万别直接用round(),要用decimal模块。
divmod(a, b)返回(a // b, a % b),也就是商和余数。这个函数在分页计算里特别好用:总共有100条数据,每页显示7条,需要多少页?
total, per_page = 100, 7 pages, remainder = divmod(total, per_page) page_count = pages + (1 if remainder else 0) # 15页sum()可以对可迭代对象求和,但注意它只能用于数字。min()和max()可以传key参数:
words = ['apple', 'banana', 'cherry'] longest = max(words, key=len) # 'banana'2.3 序列操作:len、range、enumerate、zip、sorted、reversed
len()不用多说。range()的坑在于它返回的是一个“惰性序列”,不是列表。Python 3里range(1000000)不会占用大量内存,但如果你需要反复遍历或者索引,可以先转成list。
enumerate()是我最喜欢的内置函数之一。以前写循环要维护索引:
# 老写法 index = 0 for item in items: print(index, item) index += 1 # 用enumerate for index, item in enumerate(items): print(index, item)zip()可以把多个列表“拉链式”合并:
names = ['Alice', 'Bob', 'Charlie'] scores = [85, 92, 78] for name, score in zip(names, scores): print(f'{name}: {score}')注意zip()在Python 3里返回迭代器,只能遍历一次。如果需要多次使用,转成list。
sorted()和reversed()的区别:sorted()返回新列表,reversed()返回迭代器。sorted()的key参数极其强大:
students = [ {'name': 'Alice', 'score': 85}, {'name': 'Bob', 'score': 92}, ] sorted(students, key=lambda s: s['score'], reverse=True)2.4 输入输出与对象操作:print、input、id、hash、repr、dir、help
print()的sep和end参数很多人没用过:
print('a', 'b', 'c', sep='-') # a-b-c print('hello', end=' ') print('world') # hello worldinput()永远返回字符串,需要数字要自己转。id()返回对象的内存地址,hash()返回哈希值。repr()返回对象的“官方”字符串表示,调试时比str()更有用。dir()列出对象的所有属性和方法,help()查看文档。这两个是自省利器,遇到不熟悉的库,先dir()再help()。
3. 字符串处理:文本清洗和格式化的核心工具
3.1 大小写与判断:upper、lower、title、capitalize、startswith、endswith、isdigit、isalpha
upper()和lower()做大小写转换。title()把每个单词首字母大写,capitalize()只把第一个字符大写。做用户输入规范化时,通常先strip()再lower()。
startswith()和endswith()可以传元组:
filename = 'report.pdf' if filename.endswith(('.pdf', '.doc', '.docx')): print('文档文件')isdigit()判断是否全是数字,但注意它不认负号和小数点。isalpha()判断是否全是字母。这两个在表单验证里很常用,但更复杂的验证建议用正则。
3.2 查找替换与分割:find、index、replace、split、rsplit、join、strip、lstrip、rstrip
find()找不到返回-1,index()找不到抛异常。我一般用find(),因为不想写try-except。
split()默认按空白字符分割,也可以指定分隔符和分割次数:
'2024-01-15'.split('-') # ['2024', '01', '15'] 'a,b,c,d'.split(',', 2) # ['a', 'b', 'c,d']rsplit()从右边开始分割,处理文件路径时有用。
join()是split()的逆操作,但注意它只能连接字符串列表:
'-'.join(['2024', '01', '15']) # '2024-01-15'strip()去掉首尾空白,lstrip()和rstrip()分别去左和右。它们也可以传参数去掉指定字符:
'###hello###'.strip('#') # 'hello'3.3 格式化:format、f-string、zfill、center、ljust、rjust
format()是老牌格式化方法,f-string是Python 3.6+的语法糖。我现在的代码里90%的格式化都用f-string,因为它可读性最好:
name = 'Alice' score = 92.5 print(f'{name}的分数是{score:.1f}') # Alice的分数是92.5zfill()补零,做编号生成时好用:
str(7).zfill(3) # '007'center()、ljust()、rjust()做对齐输出,写命令行工具时有用:
print('Name'.ljust(10), 'Score'.rjust(5)) print('Alice'.ljust(10), '92'.rjust(5))4. 列表、字典与集合:数据组织的三驾马车
4.1 列表操作:append、extend、insert、remove、pop、clear、index、count、sort、copy
append()加单个元素,extend()加多个元素。很多人搞混:
a = [1, 2] a.append([3, 4]) # [1, 2, [3, 4]] a.extend([3, 4]) # [1, 2, 3, 4]remove()按值删除,pop()按索引删除并返回。pop()不传参数默认删最后一个,所以列表当栈用就是append()加pop()。
sort()是原地排序,sorted()返回新列表。sort()不能对包含不可比较元素的列表使用,比如[1, 'a']会报错。
copy()是浅拷贝。嵌套列表要深拷贝得用copy.deepcopy():
import copy a = [[1, 2], [3, 4]] b = copy.deepcopy(a)4.2 字典操作:get、keys、values、items、update、pop、setdefault
get()是字典最实用的方法,没有之一:
config = {'host': 'localhost', 'port': 8080} config.get('timeout', 30) # 30items()遍历键值对:
for key, value in config.items(): print(key, value)setdefault()在键不存在时设置默认值并返回:
groups = {} groups.setdefault('admin', []).append('Alice')这行代码的意思是:如果admin键不存在,设为空列表,然后往里面加Alice。比写if-else简洁得多。
update()合并字典,Python 3.9+还可以用|运算符:
a = {'x': 1} b = {'y': 2} a.update(b) # {'x': 1, 'y': 2} # 或者 c = a | b4.3 集合操作:add、remove、union、intersection、difference、issubset
集合最大的价值是去重和快速成员判断:
nums = [1, 2, 2, 3, 3, 3] unique = list(set(nums)) # [1, 2, 3]union()并集,intersection()交集,difference()差集。做权限对比、标签匹配时特别方便:
user_a = {'read', 'write'} user_b = {'read', 'delete'} common = user_a & user_b # {'read'} only_a = user_a - user_b # {'write'}5. 文件与异常:让脚本真正能干活
5.1 文件读写:open、read、readline、readlines、write、writelines、close、with
open()的文件模式要记清楚:'r'读,'w'写(覆盖),'a'追加,'b'二进制。永远用with语句:
with open('data.txt', 'r', encoding='utf-8') as f: content = f.read()read()读全部,readline()读一行,readlines()读所有行到列表。大文件不要用read(),会爆内存。逐行读:
with open('big_file.txt', 'r', encoding='utf-8') as f: for line in f: process(line.strip())writelines()接收字符串列表,但不会自动加换行符,需要自己加:
lines = ['line1\n', 'line2\n'] with open('output.txt', 'w') as f: f.writelines(lines)5.2 异常处理:try、except、else、finally、raise、assert
try-except的基本结构:
try: result = 10 / 0 except ZeroDivisionError as e: print(f'出错了: {e}') else: print('没出错') finally: print('无论如何都执行')else在没异常时执行,finally无论如何都执行。raise主动抛异常,assert做断言(可以用-O参数禁用)。
注意:不要用裸的
except:,它会捕获所有异常包括KeyboardInterrupt,导致程序无法正常退出。至少写except Exception:。
5.3 常用标准库函数:os、sys、json、datetime、random、re
os.path.join()拼路径,os.path.exists()判断存在,os.makedirs()创建目录。sys.argv获取命令行参数,sys.exit()退出程序。
json.dumps()和json.loads()做JSON序列化和反序列化:
import json data = {'name': 'Alice', 'age': 30} json_str = json.dumps(data, ensure_ascii=False, indent=2)datetime.now()获取当前时间,strftime()格式化:
from datetime import datetime now = datetime.now() print(now.strftime('%Y-%m-%d %H:%M:%S'))random.choice()随机选一个,random.shuffle()打乱列表,random.randint()生成随机整数。
re.findall()、re.search()、re.sub()是正则三件套。处理文本清洗时,正则比字符串方法更灵活:
import re text = '联系方式: 138-1234-5678' phones = re.findall(r'\d{3}-\d{4}-\d{4}', text)6. 常见问题与排查技巧实录
6.1 函数用错场景的典型翻车现场
坑一:list.append()返回None。很多人写a = [].append(1),结果a是None。append()是原地操作,不返回新列表。
坑二:sort()和sorted()搞混。sort()只能用于列表,原地排序返回None;sorted()可用于任何可迭代对象,返回新列表。
坑三:dict.get()和dict['key']混用。dict['key']在键不存在时抛KeyError,get()返回None或默认值。不确定键是否存在时,永远用get()。
坑四:strip()去掉了不该去的字符。'hello world'.strip('h')返回'ello world',它去掉的是首尾所有h字符,不是前缀。
坑五:round()的银行家舍入。前面说过,金融计算用decimal。
6.2 性能相关的注意事项
in操作在列表上是O(n),在集合和字典上是O(1)。频繁做成员判断时,先把列表转成集合:
# 慢 if item in big_list: # O(n) # 快 big_set = set(big_list) if item in big_set: # O(1)字符串拼接用join()而不是+:
# 慢 result = '' for s in strings: result += s # 快 result = ''.join(strings)6.3 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
TypeError: 'NoneType' object is not iterable | 函数返回了None | 检查是否用了append()、sort()等原地方法的返回值 |
KeyError | 字典键不存在 | 用get()或先判断in |
IndexError | 列表索引越界 | 用len()检查长度,或用切片 |
UnicodeDecodeError | 文件编码不对 | open()时指定encoding='utf-8' |
IndentationError | 缩进不一致 | 统一用4个空格,别混用Tab |
AttributeError | 对象没有该属性 | 用dir()查看可用方法 |
6.4 我个人的实操心得
带新人的时候,我发现大家最容易犯的错不是“不知道某个函数”,而是“不知道某个函数存在”。比如不知道enumerate(),就手动维护索引;不知道setdefault(),就写一堆if-else;不知道with,就忘了close()。
我的建议是:每学一个新函数,就把它用到实际脚本里。哪怕只是把原来的三行代码改成一行,这个函数就真正变成你的了。另外,help()和dir()要养成习惯用,比搜索引擎快。
还有一个技巧:用python -i script.py进入交互模式,脚本执行完后可以继续在交互环境里试函数。调试的时候特别方便。
7. 把77个函数变成自己的工具箱
这77个函数不是让你背下来的。我的做法是:把它们按场景分类,写成一个自己的“速查笔记”,放在项目根目录的docs/下面。每次写代码遇到“这个操作好像有内置函数”的时候,先翻笔记,翻不到再搜。
另外,Python的collections、itertools、functools这几个模块里还有很多宝藏函数,比如Counter、defaultdict、chain、partial。等你把这77个用熟了,自然会想去看这些进阶工具。
最后分享一个我常用的调试技巧:在脚本里临时加一行breakpoint(),Python 3.7+会进入调试器,可以查看变量、单步执行。比到处print()高效得多。