程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

python高质量函数的20个最佳实践

hfteth 2025-05-30 14:49:55 技术文章 1 ℃

在 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 分析瓶颈!

Tags:

最近发表
标签列表