“该技能提供Python开发的核心设计模式与最佳实践,涵盖可读性、显式编程、EAFP原则、类型提示(包括现代类型注解和协议)以及错误处理模式。适用于编写、审查和重构Python代码,帮助开发者构建健壮、高效且可维护的应用程序,提升代码质量和开发效率。”

构建健壮、高效且可维护应用程序的惯用 Python 模式与最佳实践。
Python 优先考虑可读性。代码应该清晰且易于理解。
# Good: Clear and readabledef get_active_users(users: list[User]) -> list[User]: """Return only active users from the provided list.""" return [user for user in users if user.is_active]# Bad: Clever but confusingdef get_active_users(u): return [x for x in u if x.a]避免魔法;明确你的代码在做什么。
# Good: Explicit configurationimport logginglogging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')# Bad: Hidden side effectsimport some_modulesome_module.setup() # What does this do?Python 更倾向于使用异常处理而非检查条件。
# Good: EAFP styledef get_value(dictionary: dict, key: str) -> Any: try: return dictionary[key] except KeyError: return default_value# Bad: LBYL (Look Before You Leap) styledef get_value(dictionary: dict, key: str) -> Any: if key in dictionary: return dictionary[key] else: return default_valuefrom typing import Optional, List, Dict, Anydef process_user( user_id: str, data: Dict[str, Any], active: bool = True) -> Optional[User]: """Process a user and return the updated User or None.""" if not active: return None return User(user_id, data)# Python 3.9+ - Use built-in typesdef process_items(items: list[str]) -> dict[str, int]: return {item: len(item) for item in items}# Python 3.8 and earlier - Use typing modulefrom typing import List, Dictdef process_items(items: List[str]) -> Dict[str, int]: return {item: len(item) for item in items}from typing import TypeVar, Union# Type alias for complex typesJSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]def parse_json(data: str) -> JSON: return json.loads(data)# Generic typesT = TypeVar('T')def first(items: list[T]) -> T | None: """Return the first item or None if list is empty.""" return items[0] if items else Nonefrom typing import Protocolclass Renderable(Protocol): def render(self) -> str: """Render the object to a string."""def render_all(items: list[Renderable]) -> str: """Render all items that implement the Renderable protocol.""" return "\n".join(item.render() for item in items)# Good: Catch specific exceptionsdef load_config(path: str) -> Config: try: with open(path) as f: return Config.from_json(f.read()) except FileNotFoundError as e: raise ConfigError(f"Config file not found: {path}") from e except json.JSONDecodeError as e: raise ConfigError(f"Invalid JSON in config: {path}") from e# Bad: Bare exceptdef load_config(path: str) -> Config: try: with open(path) as f: return Config.from_json(f.read()) except: return None # Silent failure!def process_data(data: str) -> Result: try: parsed = json.loads(data) except json.JSONDecodeError as e: # Chain exceptions to preserve the traceback raise ValueError(f"Failed to parse data: {data}") from eclass AppError(Exception): """Base exception for all application errors.""" passclass ValidationError(AppError): """Raised when input validation fails.""" passclass NotFoundError(AppError): """Raised when a requested resource is not found.""" pass# Usagedef get_user(user_id: str) -> User: user = db.find_user(user_id) if not user: raise NotFoundError(f"User not found: {user_id}") return user# Good: Using context managersdef process_file(path: str) -> str: with open(path, 'r') as f: return f.read()# Bad: Manual resource managementdef process_file(path: str) -> str: f = open(path, 'r') try: return f.read() finally: f.close()from contextlib import contextmanager@contextmanagerdef timer(name: str): """Context manager to time a block of code.""" start = time.perf_counter() yield elapsed = time.perf_counter() - start print(f"{name} took {elapsed:.4f} seconds")# Usagewith timer("data processing"): process_large_dataset()class DatabaseTransaction: def __init__(self, connection): self.connection = connection def __enter__(self): self.connection.begin_transaction() return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is None: self.connection.commit() else: self.connection.rollback() return False # Don't suppress exceptions# Usagewith DatabaseTransaction(conn): user = conn.create_user(user_data) conn.create_profile(user.id, profile_data)# Good: List comprehension for simple transformationsnames = [user.name for user in users if user.is_active]# Bad: Manual loopnames = []for user in users: if user.is_active: names.append(user.name)# Complex comprehensions should be expanded# Bad: Too complexresult = [x * 2 for x in items if x > 0 if x % 2 == 0]# Good: Use a generator functiondef filter_and_transform(items: Iterable[int]) -> list[int]: result = [] for x in items: if x > 0 and x % 2 == 0: result.append(x * 2) return result# Good: Generator for lazy evaluationtotal = sum(x * x for x in range(1_000_000))# Bad: Creates large intermediate listtotal = sum([x * x for x in range(1_000_000)])def read_large_file(path: str) -> Iterator[str]: """Read a large file line by line.""" with open(path) as f: for line in f: yield line.strip()# Usagefor line in read_large_file("huge.txt"): process(line)from dataclasses import dataclass, fieldfrom datetime import datetime@dataclassclass User: """User entity with automatic __init__, __repr__, and __eq__.""" id: str name: str email: str created_at: datetime = field(default_factory=datetime.now) is_active: bool = True# Usageuser = User( id="123", name="Alice", email="alice@example.com")@dataclassclass User: email: str age: int def __post_init__(self): # Validate email format if "@" not in self.email: raise ValueError(f"Invalid email: {self.email}") # Validate age range if self.age < 0 or self.age > 150: raise ValueError(f"Invalid age: {self.age}")from typing import NamedTupleclass Point(NamedTuple): """Immutable 2D point.""" x: float y: float def distance(self, other: 'Point') -> float: return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5# Usagep1 = Point(0, 0)p2 = Point(3, 4)print(p1.distance(p2)) # 5.0import functoolsimport timedef timer(func: Callable) -> Callable: """Decorator to time function execution.""" @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start print(f"{func.__name__} took {elapsed:.4f}s") return result return wrapper@timerdef slow_function(): time.sleep(1)# slow_function() prints: slow_function took 1.0012sdef repeat(times: int): """Decorator to repeat a function multiple times.""" def decorator(func: Callable) -> Callable: @functools.wraps(func) def wrapper(*args, **kwargs): results = [] for _ in range(times): results.append(func(*args, **kwargs)) return results return wrapper return decorator@repeat(times=3)def greet(name: str) -> str: return f"Hello, {name}!"# greet("Alice") returns ["Hello, Alice!", "Hello, Alice!", "Hello, Alice!"]class CountCalls: """Decorator that counts how many times a function is called.""" def __init__(self, func: Callable): functools.update_wrapper(self, func) self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.func.__name__} has been called {self.count} times") return self.func(*args, **kwargs)@CountCallsdef process(): pass# Each call to process() prints the call countimport concurrent.futuresimport threadingdef fetch_url(url: str) -> str: """Fetch a URL (I/O-bound operation).""" import urllib.request with urllib.request.urlopen(url) as response: return response.read().decode()def fetch_all_urls(urls: list[str]) -> dict[str, str]: """Fetch multiple URLs concurrently using threads.""" with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: future_to_url = {executor.submit(fetch_url, url): url for url in urls} results = {} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: results[url] = future.result() except Exception as e: results[url] = f"Error: {e}" return resultsdef process_data(data: list[int]) -> int: """CPU-intensive computation.""" return sum(x ** 2 for x in data)def process_all(datasets: list[list[int]]) -> list[int]: """Process multiple datasets using multiple processes.""" with concurrent.futures.ProcessPoolExecutor() as executor: results = list(executor.map(process_data, datasets)) return resultsimport asyncioasync def fetch_async(url: str) -> str: """Fetch a URL asynchronously.""" import aiohttp async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text()async def fetch_all(urls: list[str]) -> dict[str, str]: """Fetch multiple URLs concurrently.""" tasks = [fetch_async(url) for url in urls] results = await asyncio.gather(*tasks, return_exceptions=True) return dict(zip(urls, results))myproject/├── src/│ └── mypackage/│ ├── __init__.py│ ├── main.py│ ├── api/│ │ ├── __init__.py│ │ └── routes.py│ ├── models/│ │ ├── __init__.py│ │ └── user.py│ └── utils/│ ├── __init__.py│ └── helpers.py├── tests/│ ├── __init__.py│ ├── conftest.py│ ├── test_api.py│ └── test_models.py├── pyproject.toml├── README.md└── .gitignore# Good: Import order - stdlib, third-party, localimport osimport sysfrom pathlib import Pathimport requestsfrom fastapi import FastAPIfrom mypackage.models import Userfrom mypackage.utils import format_name# Good: Use isort for automatic import sorting# pip install isort# mypackage/__init__.py"""mypackage - A sample Python package."""__version__ = "1.0.0"# Export main classes/functions at package levelfrom mypackage.models import User, Postfrom mypackage.utils import format_name__all__ = ["User", "Post", "format_name"]# Bad: Regular class uses __dict__ (more memory)class Point: def __init__(self, x: float, y: float): self.x = x self.y = y# Good: __slots__ reduces memory usageclass Point: __slots__ = ['x', 'y'] def __init__(self, x: float, y: float): self.x = x self.y = y# Bad: Returns full list in memorydef read_lines(path: str) -> list[str]: with open(path) as f: return [line.strip() for line in f]# Good: Yields lines one at a timedef read_lines(path: str) -> Iterator[str]: with open(path) as f: for line in f: yield line.strip()# Bad: O(n²) due to string immutabilityresult = ""for item in items: result += str(item)# Good: O(n) using joinresult = "".join(str(item) for item in items)# Good: Using StringIO for buildingfrom io import StringIObuffer = StringIO()for item in items: buffer.write(str(item))result = buffer.getvalue()# Code formattingblack .isort .# Lintingruff check .pylint mypackage/# Type checkingmypy .# Testingpytest --cov=mypackage --cov-report=html# Security scanningbandit -r .# Dependency managementpip-auditsafety check[project]name = "mypackage"version = "1.0.0"requires-python = ">=3.9"dependencies = [ "requests>=2.31.0", "pydantic>=2.0.0",][project.optional-dependencies]dev = [ "pytest>=7.4.0", "pytest-cov>=4.1.0", "black>=23.0.0", "ruff>=0.1.0", "mypy>=1.5.0",][tool.black]line-length = 88target-version = ['py39'][tool.ruff]line-length = 88select = ["E", "F", "I", "N", "W"][tool.mypy]python_version = "3.9"warn_return_any = truewarn_unused_configs = truedisallow_untyped_defs = true[tool.pytest.ini_options]testpaths = ["tests"]addopts = "--cov=mypackage --cov-report=term-missing"with 进行资源管理 | |
__slots__ | |
pathlib.Path | |
enumerate |
# Bad: Mutable default argumentsdef append_to(item, items=[]): items.append(item) return items# Good: Use None and create new listdef append_to(item, items=None): if items is None: items = [] items.append(item) return items# Bad: Checking type with type()if type(obj) == list: process(obj)# Good: Use isinstanceif isinstance(obj, list): process(obj)# Bad: Comparing to None with ==if value == None: process()# Good: Use isif value is None: process()# Bad: from module import *from os.path import *# Good: Explicit importsfrom os.path import join, exists# Bad: Bare excepttry: risky_operation()except: pass# Good: Specific exceptiontry: risky_operation()except SpecificError as e: logger.error(f"Operation failed: {e}")记住:Python 代码应该具有可读性、显式性,并遵循最小意外原则。如有疑问,优先考虑清晰度而非巧妙性。
请在微信客户端打开
安装命令
npx skills add https://github.com/affaan-m/everything-claude-code --skill python-patterns每周安装量:1.0K
代码仓库:https://github.com/affaan-m/everything-claude-code
GitHub 星标:70.6K
首次出现:2026年2月1日
安全审计:Gen Agent Trust HubPass SocketPass SnykPass
安装于:opencode859,codex849,gemini-cli812,github-copilot769,kimi-cli716,amp711
更多技能>>>
find-skills 技能搜索工具 - 让AI更智能的skill
Skills之创业公司团队构成分析:种子轮到A轮招聘、薪酬与股权分配指南 GitHub Stars 35K+
Skills之OpenAI图像生成技能:AI绘图、图片编辑与批量生成,支持网站素材、UI设计、产品模型 GitHub Stars 1.7万+
Skills之Google Stitch UI设计提示指南:AI驱动UI生成工具使用技巧与最佳实践 GitHub Stars 3.5万+
Skills之Excel财务建模规范与xlsx文件处理指南:专业格式、零错误公式与数据分析 GitHub Stars 12万+
Skills之办公自动化工作流套件:LibreOffice与Microsoft Office文档创建、电子表格自动化、演示文稿生成与格式转换 GitHub Stars 3.5+
