关于 python-best-practices
为 Python 开发提供代码质量与一致性指导的技能,适用于编写、重构和维护 Python 项目。内容涵盖 PEP 8、类型提示、文档字符串、错误处理与常见代码组织模式。
主要功能
- 01PEP 8 风格规范
- 02类型提示与现代语法
- 03NumPy 风格文档字符串
- 04异常处理与上下文管理器
- 05数据类、枚举与 pathlib
- 06pytest 测试实践
适用场景
- 01编写符合一致风格的 Python 代码
- 02为函数与类补充类型提示和文档
- 03重构文件与模块组织
- 04改进异常处理和文件操作
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jefflester/ claude-skills-supercharged --skill python-best-practices安装后在 Claude Code 中输入/python-best-practices确认已加载。
详细介绍
Python 最佳实践
目的
本技能提供 Python 开发最佳实践指南,帮助确保 Python 项目中的代码质量、可维护性和一致性。
何时使用此技能
在以下情况下自动激活:
- 处理 Python 文件(*.py)
- 提及“python”“best practices”“style guide”
- 添加类型提示或文档字符串
- 重构 Python 代码
风格指南
遵循 PEP 8
遵循 Python 代码的 PEP 8 风格指南:
- 缩进:每级缩进 4 个空格
- 行长度:代码最多 79 个字符,文档字符串/注释最多 72 个字符
- 空行:顶层定义之间空 2 行,方法之间空 1 行
- 导入:始终放在文件顶部,并按标准库、第三方库、本地模块分组
- 命名约定:
- 函数、变量和模块使用
snake_case - 类使用
PascalCase - 常量使用
UPPER_SNAKE_CASE - 内部/私有名称以下划线
_name开头
- 函数、变量和模块使用
导入组织
始终按以下顺序组织导入:
# 1. Standard library imports
import os
import sys
from pathlib import Path
# 2. Third-party imports
import requests
import numpy as np
# 3. Local application imports
from myapp.core import MyClass
from myapp.utils import helper_function
使用 TYPE_CHECKING 避免循环导入:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from myapp.other_module import OtherClass
def my_function(obj: "OtherClass") -> None:
"""Function that uses OtherClass only for type hints."""
pass
类型提示
始终使用类型提示
类型提示有助于提高代码清晰度并及早发现错误:
def process_data(
items: list[str],
max_count: int | None = None,
verbose: bool = False
) -> dict[str, int]:
"""Process items and return counts.
Parameters
----------
items : list[str]
List of items to process
max_count : int | None, optional
Maximum items to process, by default None
verbose : bool, optional
Enable verbose output, by default False
Returns
-------
dict[str, int]
Dictionary mapping items to counts
"""
result: dict[str, int] = {}
for item in items[:max_count]:
result[item] = result.get(item, 0) + 1
if verbose:
print(f"Processed: {item}")
return result
现代类型语法(Python 3.10+)
使用现代联合类型语法 |,而不是 Union:
# Good (Python 3.10+)
def get_value(key: str) -> int | None:
pass
# Avoid (old style)
from typing import Union, Optional
def get_value(key: str) -> Optional[int]:
pass
泛型类型
使用内置泛型类型(Python 3.9+):
# Good (Python 3.9+)
def process_list(items: list[str]) -> dict[str, int]:
pass
# Avoid (old style)
from typing import List, Dict
def process_list(items: List[str]) -> Dict[str, int]:
pass
文档字符串
NumPy 风格文档字符串
使用 NumPy 风格的文档字符串,以保持一致性:
def calculate_statistics(
data: list[float],
include_median: bool = True
) -> dict[str, float]:
"""Calculate statistical measures for a dataset.
This function computes mean, standard deviation, and optionally
median for the provided dataset.
Parameters
----------
data : list[float]
List of numerical values to analyze
include_median : bool, optional
Whether to calculate median, by default True
Returns
-------
dict[str, float]
Dictionary containing:
- 'mean': arithmetic mean
- 'std': standard deviation
- 'median': median value (if include_median=True)
Raises
------
ValueError
If data is empty or contains non-numeric values
Examples
--------
>>> calculate_statistics([1.0, 2.0, 3.0, 4.0, 5.0])
{'mean': 3.0, 'std': 1.414, 'median': 3.0}
Notes
-----
Standard deviation uses Bessel's correction (ddof=1).
"""
if not data:
raise ValueError("Data cannot be empty")
# Implementation here
pass
类文档字符串
class DataProcessor:
"""Process and transform data from various sources.
This class provides methods for loading, transforming, and
validating data from multiple input formats.
Parameters
----------
source_dir : Path
Directory containing source data files
cache_enabled : bool, optional
Enable result caching, by default True
Attributes
----------
source_dir : Path
Directory path for source files
cache : dict[str, Any]
Cache for processed results
Examples
--------
>>> processor = DataProcessor(Path("/data"))
>>> results = processor.process_files()
"""
def __init__(self, source_dir: Path, cache_enabled: bool = True):
"""Initialize the DataProcessor."""
self.source_dir = source_dir
self.cache: dict[str, Any] = {} if cache_enabled else None
错误处理
指定异常类型
使用指定的异常类型,不要使用裸 except:
# Good
try:
with open(file_path) as f:
data = f.read()
except FileNotFoundError:
logger.error(f"File not found: {file_path}")
raise
except PermissionError:
logger.error(f"Permission denied: {file_path}")
raise
# Avoid
try:
with open(file_path) as f:
data = f.read()
except: # Too broad!
pass
上下文管理器
始终使用上下文管理器管理资源:
# Good
with open(file_path) as f:
content = f.read()
# Avoid
f = open(file_path)
content = f.read()
f.close() # Easy to forget!
自定义异常
为特定领域的错误定义自定义异常:
class ValidationError(Exception):
"""Raised when data validation fails."""
pass
class DataProcessingError(Exception):
"""Raised when data processing encounters an error."""
def __init__(self, message: str, item_id: str):
super().__init__(message)
self.item_id = item_id
常见模式
使用数据类表示数据结构
对于简单的数据容器,使用 dataclasses:
from dataclasses import dataclass, field
@dataclass
class User:
"""User profile information."""
username: str
email: str
age: int
tags: list[str] = field(default_factory=list)
is_active: bool = True
def __post_init__(self):
"""Validate fields after initialization."""
if self.age < 0:
raise ValueError("Age cannot be negative")
使用枚举表示固定集合
使用 Enum 表示固定的值集合:
from enum import Enum, auto
class Status(Enum):
"""Processing status values."""
PENDING = auto()
PROCESSING = auto()
COMPLETED = auto()
FAILED = auto()
# Usage
current_status = Status.PENDING
if current_status == Status.COMPLETED:
print("Done!")
使用 Pathlib 进行文件操作
使用 pathlib.Path,而不是 os.path:
from pathlib import Path
# Good
data_dir = Path("/data")
file_path = data_dir / "input.txt"
if file_path.exists():
content = file_path.read_text()
# Avoid
import os
data_dir = "/data"
file_path = os.path.join(data_dir, "input.txt")
if os.path.exists(file_path):
with open(file_path) as f:
content = f.read()
列表推导式
使用推导式提升清晰度和性能:
# Good
squared = [x**2 for x in range(10) if x % 2 == 0]
# Avoid
squared = []
for x in range(10):
if x % 2 == 0:
squared.append(x**2)
代码组织
模块结构
将模块划分为清晰的部分:
"""Module for data processing utilities.
This module provides functions for loading, transforming, and
validating data from various sources.
"""
# Standard library imports
import os
import sys
from pathlib import Path
# Third-party imports
import requests
import pandas as pd
# Local imports
from myapp.core import BaseProcessor
from myapp.utils import validate_input
# Constants
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
# Exceptions
class ProcessingError(Exception):
"""Raised when processing fails."""
pass
# Functions
def load_data(source: str) -> pd.DataFrame:
"""Load data from source."""
pass
# Classes
class DataProcessor(BaseProcessor):
"""Process and validate data."""
pass
# Module initialization
if __name__ == "__main__":
# CLI entry point
main()
避免魔法数字
使用命名常量,而不是魔法数字:
# Good
MAX_RETRIES = 3
TIMEOUT_SECONDS = 30
def fetch_data(url: str) -> dict:
for attempt in range(MAX_RETRIES):
response = requests.get(url, timeout=TIMEOUT_SECONDS)
if response.status_code == 200:
return response.json()
# Avoid
def fetch_data(url: str) -> dict:
for attempt in range(3): # What is 3?
response = requests.get(url, timeout=30) # Why 30?
if response.status_code == 200:
return response.json()
测试
使用 pytest 进行测试
import pytest
from myapp.processor import DataProcessor
def test_process_valid_data():
"""Test processing with valid input."""
processor = DataProcessor()
result = processor.process([1, 2, 3])
assert result == [2, 4, 6]
def test_process_empty_data():
"""Test processing with empty input."""
processor = DataProcessor()
with pytest.raises(ValueError):
processor.process([])
@pytest.fixture
def sample_data():
"""Provide sample data for tests."""
return [1, 2, 3, 4, 5]
def test_with_fixture(sample_data):
"""Test using fixture."""
processor = DataProcessor()
result = processor.process(sample_data)
assert len(result) == len(sample_data)
要点总结
- 始终遵循 PEP 8 风格指南
- 始终为函数签名添加类型提示
- 为所有公共函数/类编写 NumPy 风格的文档字符串
- 使用指定的异常类型,不要使用裸
except - 优先使用
pathlib.Path,而不是os.path - 使用数据类和枚举表示结构化数据
- 按标准库 → 第三方库 → 本地模块的顺序组织导入
- 避免使用魔法数字,改用命名常量
- 使用 pytest 编写测试
- 使用现代 Python 语法(3.9+)
评论
支持 Markdown