python高质量函数的20个最佳实践
在 Python 中编写高质量函数需遵循以下 20 个最佳实践,涵盖代码规范、性能优化和可维护性,附代码示例与深度解析:
一、函数设计原则
1.单一职责原则
原则:一个函数只做一件事
反例:
def process_data(data):
cleaned = [x.strip() for x in data] # 职责1:清洗数据
avg = sum(cleaned)/len(cleaned) # 职责2:计算均值
return cleaned, avg
正例:
def clean_data(data):
return [x.strip() for x in data]
def calculate_average(cleaned_data):
return sum(cleaned_data)/len(cleaned_data)
2.明确函数名
规范:
- 动词+名词:get_user_info
- 避免模糊词:handle_data → convert_to_json
- 全小写下划线:符合 PEP8 规范
二、参数处理规范
3.类型提示(Type Hints)
def format_name(first: str, last: str, middle: str = "") -> str:
return f"{last}, {first} {middle}".strip()
4.避免可变默认参数
错误:
def add_item(item, items=[]): # 默认列表会共享
items.append(item)
return items
正确:
def add_item(item, items=None):
items = items or []
items.append(item)
return items
5.参数顺序规范
推荐顺序:
def func(positional_args, *args, keyword_only_args, **kwargs):
pass
三、返回值与异常
6.返回一致性
推荐:返回同类型或明确结构
# 返回字典统一结构
def get_user(id):
# ...
return {"id": 1, "name": "Alice"} # 错误时返回None或空字典
7.异常替代错误码
反例:
def divide(a, b):
if b == 0:
return -1 # 错误码混淆正常结果
return a / b
正例:
def divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("除数不能为零")
return a / b
8.精确捕获异常
避免笼统捕获:
try:
risky_operation()
except Exception as e: # 可能掩盖问题
logger.error(e)
推荐
try:
risky_operation()
except (FileNotFoundError, PermissionError) as e:
logger.error(f"文件操作失败: {e}")
四、性能优化
9.局部变量加速访问
def calculate(data):
len_data = len(data) # 避免循环中重复调用len()
return sum(x * x for x in data) / len_data
10.缓存重复计算
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
五、高级技巧
11.用生成器替代返回列表
节省内存:
def read_large_file(file_path):
with open(file_path) as f:
for line in f:
yield line.strip()
12.装饰器增强功能
from functools import wraps
import time
def timer(func):
@wraps(func) # 保留元数据
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"耗时: {time.perf_counter() - start:.2f}s")
return result
return wrapper
@timer
def process_data(data):
# 数据处理逻辑
六、代码可维护性
13.详尽文档字符串
def calculate_interest(principal: float, rate: float, years: int) -> float:
"""
计算复利利息
Args:
principal: 本金(必须为正数)
rate: 年利率(如0.05表示5%)
years: 投资年限(至少1年)
Returns:
总金额(本金 + 利息)
Raises:
ValueError: 输入参数不合法时抛出
"""
if principal <= 0 or rate <= 0 or years < 1:
raise ValueError("无效输入参数")
return principal * (1 + rate) ** years
14.防御式编程
def send_email(to: str, subject: str, body: str) -> bool:
if not validate_email(to):
logger.error("邮箱格式错误")
return False
# 发送逻辑...
七、测试与调试
15.可测试性设计
避免副作用:
# 难测试(直接写入文件)
def generate_report(data):
with open("report.txt", "w") as f:
f.write(str(data))
# 改进(返回内容,由调用者决定写入)
def generate_report(data) -> str:
return "\n".join(str(item) for item in data)
16.单元测试覆盖
import unittest
class TestInterest(unittest.TestCase):
def test_normal_case(self):
self.assertAlmostEqual(calculate_interest(1000, 0.05, 5), 1276.28, places=2)
def test_invalid_input(self):
with self.assertRaises(ValueError):
calculate_interest(-1000, 0.05, 5)
八、函数式编程
17.高阶函数应用
from typing import Callable
def apply_operation(func: Callable[[int], int], data: list) -> list:
return [func(x) for x in data]
apply_operation(lambda x: x*2, [1,2,3]) # [2,4,6]
18.闭包封装状态
def counter() -> Callable[[], int]:
count = 0
def _increment() -> int:
nonlocal count
count += 1
return count
return _increment
c = counter()
print(c(), c()) # 1, 2
九、代码规范工具
19.强制格式检查
- Pylint:检查 PEP8 规范
- Black:自动格式化代码
- Mypy:静态类型检查
配置示例(pyproject.toml):
[tool.black]
line-length = 88
[tool.mypy]
strict = true
十、性能对比与选择
场景 | 推荐方案 | 性能提升 |
列表过滤 | 列表推导式 | 比 for 快 1.5x |
大量条件判断 | 字典分派 (Dispatch) | 比 if-elif 快 3x |
递归深度较大 | 循环替代 | 避免栈溢出 |
字典分派示例:
def handle_a():
pass
def handle_b():
pass
handlers = {"case_a": handle_a, "case_b": handle_b}
handlers[case]() # 替代多个if判断
掌握这些最佳实践后,你的 Python 函数将具备以下优势:
可读性提升 50%
维护成本降低 70%
性能优化 2-10 倍
持续改进:定期用 timeit 测试关键函数性能,使用 cProfile 分析瓶颈!