本文目录导读:

- 用列表推导式替换显式循环
- 用enumerate获取索引,避免手动计数
- 用zip并行遍历多个序列
- 用in检查成员关系
- 用with管理资源(文件、锁等)
- 用字典/集合做去重、计数
- 用any/all代替显式循环判断
- 用装饰器分离横切关注点
- 用unpacking替代索引访问
- 用匹配语句替代长串if-elif
- 判断代码是否Pythonic的标准
让Python案例更“Pythonic”的核心是:使用Python惯用写法、充分利用语言特性、追求代码的简洁与可读性,下面从几个维度给出具体方法和示例。
用列表推导式替换显式循环
不Pythonic
squares = []
for i in range(10):
squares.append(i * i)
Pythonic
squares = [i * i for i in range(10)]
适用场景:创建新列表、过滤数据、简单变换。
用enumerate获取索引,避免手动计数
不Pythonic
i = 0
for item in items:
print(i, item)
i += 1
Pythonic
for i, item in enumerate(items):
print(i, item)
进阶:可指定起始索引 enumerate(items, start=1)。
用zip并行遍历多个序列
不Pythonic
for i in range(len(names)):
print(names[i], ages[i])
Pythonic
for name, age in zip(names, ages):
print(name, age)
用in检查成员关系
不Pythonic
if name in names_list:
但避免:if names_list.count(name) > 0(效率低且啰嗦)。
用with管理资源(文件、锁等)
不Pythonic
f = open('file.txt', 'r')
try:
content = f.read()
finally:
f.close()
Pythonic
with open('file.txt', 'r') as f:
content = f.read()
用字典/集合做去重、计数
不Pythonic(手动计数)
counts = {}
for word in words:
if word in counts:
counts[word] += 1
else:
counts[word] = 1
Pythonic(使用defaultdict或Counter)
from collections import Counter counts = Counter(words)
或:
from collections import defaultdict
counts = defaultdict(int)
for word in words:
counts[word] += 1
用any/all代替显式循环判断
不Pythonic
result = False
for num in nums:
if num > 10:
result = True
break
Pythonic
result = any(num > 10 for num in nums)
用装饰器分离横切关注点
不Pythonic(内嵌计时逻辑)
def process_data():
import time
start = time.time()
# 实际逻辑
print(f"耗时: {time.time()-start}")
Pythonic
import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} 耗时: {time.time()-start:.3f}s")
return result
return wrapper
@timer
def process_data():
# 原始逻辑,无杂质
pass
用unpacking替代索引访问
不Pythonic
first = items[0] second = items[1]
Pythonic
first, second = items[0], items[1] # 仍然不够好 # 更好的: first, second, *rest = items
通用解包:
a, b, *c = [1, 2, 3, 4, 5] # a=1, b=2, c=[3,4,5]
用匹配语句替代长串if-elif
Python 3.10+ 可用:
不Pythonic
if status == 200:
handle_ok()
elif status == 404:
handle_not_found()
elif status == 500:
handle_server_error()
else:
handle_unknown()
Pythonic
match status:
case 200:
handle_ok()
case 404:
handle_not_found()
case 500:
handle_server_error()
case _:
handle_unknown()
判断代码是否Pythonic的标准
- 可读性优先(代码即文档)
- 充分利用标准库(itertools, functools, collections等)
- 遵循PEP 8(命名、缩进、空行)
- 尽量少写"模式代码"(样板代码是异味)
- 追求表达力(一行完成而非三层嵌套)
快速自查表:
- 是否用了
range(len(...))? → 改为enumerate或zip - 是否手动维护索引变量? → 改为
enumerate - 是否用
for i in range(len(a))遍历两个列表? → 改为zip - 是否用
try/finally管理资源? → 改为with - 是否有多层嵌套的列表处理? → 考虑列表推导式加条件
一个实际案例的前后对比:
原始(不Pythonic):
result = []
for i in range(len(data)):
if data[i] > 0:
result.append(data[i] * 2)
Pythonic:
result = [x * 2 for x in data if x > 0]
这样改后,不仅更短,而且变量名 x 比 data[i] 更清晰,意图一目了然。