Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
python-patterns
description
Pythonic idioms, PEP 8 standards, type hints, and best practices for building robust, efficient, and maintainable Python applications.
origin
ECC
Python Development Patterns
Idiomatic Python patterns and best practices for building robust, efficient, and maintainable applications.
When to Activate
Writing new Python code
Reviewing Python code
Refactoring existing Python code
Designing Python packages/modules
Core Principles
1. Readability Counts
Python prioritizes readability. Code should be obvious and easy to understand.
# Good: Clear and readabledefget_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 confusingdefget_active_users(u):
return [x for x in u if x.a]
2. Explicit is Better Than Implicit
Avoid magic; be clear about what your code does.
# Good: Explicit configurationimport logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Bad: Hidden side effectsimport some_module
some_module.setup() # What does this do?
3. EAFP - Easier to Ask Forgiveness Than Permission
Python prefers exception handling over checking conditions.
# Good: EAFP styledefget_value(dictionary: dict, key: str) -> Any:
try:
return dictionary[key]
except KeyError:
return default_value
# Bad: LBYL (Look Before You Leap) styledefget_value(dictionary: dict, key: str) -> Any:
if key in dictionary:
return dictionary[key]
else:
return default_value
Type Hints
Basic Type Annotations
from typing importOptional, List, Dict, Anydefprocess_user(
user_id: str,
data: Dict[str, Any],
active: bool = True) -> Optional[User]:
"""Process a user and return the updated User or None."""ifnot active:
returnNonereturn User(user_id, data)
Modern Type Hints (Python 3.9+)
# Python 3.9+ - Use built-in typesdefprocess_items(items: list[str]) -> dict[str, int]:
return {item: len(item) for item in items}
# Python 3.8 and earlier - Use typing modulefrom typing importList, Dictdefprocess_items(items: List[str]) -> Dict[str, int]:
return {item: len(item) for item in items}
Type Aliases and TypeVar
from typing import TypeVar, Union# Type alias for complex types
JSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]
defparse_json(data: str) -> JSON:
return json.loads(data)
# Generic types
T = TypeVar('T')
deffirst(items: list[T]) -> T | None:
"""Return the first item or None if list is empty."""return items[0] if items elseNone
Protocol-Based Duck Typing
from typing import Protocol
classRenderable(Protocol):
defrender(self) -> str:
"""Render the object to a string."""defrender_all(items: list[Renderable]) -> str:
"""Render all items that implement the Renderable protocol."""return"\n".join(item.render() for item in items)
Error Handling Patterns
Specific Exception Handling
# Good: Catch specific exceptionsdefload_config(path: str) -> Config:
try:
withopen(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 exceptdefload_config(path: str) -> Config:
try:
withopen(path) as f:
return Config.from_json(f.read())
except:
returnNone# Silent failure!
Exception Chaining
defprocess_data(data: str) -> Result:
try:
parsed = json.loads(data)
except json.JSONDecodeError as e:
# Chain exceptions to preserve the tracebackraise ValueError(f"Failed to parse data: {data}") from e
Custom Exception Hierarchy
classAppError(Exception):
"""Base exception for all application errors."""passclassValidationError(AppError):
"""Raised when input validation fails."""passclassNotFoundError(AppError):
"""Raised when a requested resource is not found."""pass# Usagedefget_user(user_id: str) -> User:
user = db.find_user(user_id)
ifnot user:
raise NotFoundError(f"User not found: {user_id}")
return user
# Good: List comprehension for simple transformations
names = [user.name for user in users if user.is_active]
# Bad: Manual loop
names = []
for user in users:
if user.is_active:
names.append(user.name)
# Complex comprehensions should be expanded# Bad: Too complex
result = [x * 2for x in items if x > 0if x % 2 == 0]
# Good: Use a generator functiondeffilter_and_transform(items: Iterable[int]) -> list[int]:
result = []
for x in items:
if x > 0and x % 2 == 0:
result.append(x * 2)
return result
Generator Expressions
# Good: Generator for lazy evaluation
total = sum(x * x for x inrange(1_000_000))
# Bad: Creates large intermediate list
total = sum([x * x for x inrange(1_000_000)])
Generator Functions
defread_large_file(path: str) -> Iterator[str]:
"""Read a large file line by line."""withopen(path) as f:
for line in f:
yield line.strip()
# Usagefor line in read_large_file("huge.txt"):
process(line)
Data Classes and Named Tuples
Data Classes
from dataclasses import dataclass, field
from datetime import datetime
@dataclassclassUser:
"""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# Usage
user = User(
id="123",
name="Alice",
email="alice@example.com"
)
classCountCalls:
"""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 = 0def__call__(self, *args, **kwargs):
self.count += 1print(f"{self.func.__name__} has been called {self.count} times")
returnself.func(*args, **kwargs)
@CountCallsdefprocess():
pass# Each call to process() prints the call count
Concurrency Patterns
Threading for I/O-Bound Tasks
import concurrent.futures
import threading
deffetch_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()
deffetch_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 results
Multiprocessing for CPU-Bound Tasks
defprocess_data(data: list[int]) -> int:
"""CPU-intensive computation."""returnsum(x ** 2for x in data)
defprocess_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 results
Async/Await for Concurrent I/O
import asyncio
asyncdeffetch_async(url: str) -> str:
"""Fetch a URL asynchronously."""import aiohttp
asyncwith aiohttp.ClientSession() as session:
asyncwith session.get(url) as response:
returnawait response.text()
asyncdeffetch_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)
returndict(zip(urls, results))
# Good: Import order - stdlib, third-party, localimport os
import sys
from pathlib import Path
import requests
from fastapi import FastAPI
from mypackage.models import User
from mypackage.utils import format_name
# Good: Use isort for automatic import sorting# pip install isort
init.py for Package Exports
# mypackage/__init__.py"""mypackage - A sample Python package."""
__version__ = "1.0.0"# Export main classes/functions at package levelfrom mypackage.models import User, Post
from mypackage.utils import format_name
__all__ = ["User", "Post", "format_name"]
Memory and Performance
Using slots for Memory Efficiency
# Bad: Regular class uses __dict__ (more memory)classPoint:
def__init__(self, x: float, y: float):
self.x = x
self.y = y
# Good: __slots__ reduces memory usageclassPoint:
__slots__ = ['x', 'y']
def__init__(self, x: float, y: float):
self.x = x
self.y = y
Generator for Large Data
# Bad: Returns full list in memorydefread_lines(path: str) -> list[str]:
withopen(path) as f:
return [line.strip() for line in f]
# Good: Yields lines one at a timedefread_lines(path: str) -> Iterator[str]:
withopen(path) as f:
for line in f:
yield line.strip()
Avoid String Concatenation in Loops
# Bad: O(n²) due to string immutability
result = ""for item in items:
result += str(item)
# Good: O(n) using join
result = "".join(str(item) for item in items)
# Good: Using StringIO for buildingfrom io import StringIO
buffer = StringIO()
for item in items:
buffer.write(str(item))
result = buffer.getvalue()