python-patterns
Patrones idiomáticos de Python, estándares PEP 8, type hints y buenas prácticas para construir aplicaciones Python robustas, eficientes y mantenibles.
What this skill does
# Patrones de Desarrollo Python
Patrones idiomáticos de Python y buenas prácticas para construir aplicaciones robustas, eficientes y mantenibles.
## Cuándo Activar
- Escribir código Python nuevo
- Revisar código Python
- Refactorizar código Python existente
- Diseñar paquetes/módulos Python
## Principios Fundamentales
### 1. La Legibilidad Cuenta
Python prioriza la legibilidad. El código debe ser obvio y fácil de entender.
```python
# Bien: Claro y legible
def get_active_users(users: list[User]) -> list[User]:
"""Retorna solo los usuarios activos de la lista proporcionada."""
return [user for user in users if user.is_active]
# Mal: Inteligente pero confuso
def get_active_users(u):
return [x for x in u if x.a]
```
### 2. Explícito es Mejor que Implícito
Evitar la magia; ser claro sobre lo que hace el código.
```python
# Bien: Configuración explícita
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Mal: Efectos secundarios ocultos
import some_module
some_module.setup() # ¿Qué hace esto?
```
### 3. EAFP - Es Más Fácil Pedir Perdón que Permiso
Python prefiere el manejo de excepciones sobre verificar condiciones.
```python
# Bien: Estilo EAFP
def get_value(dictionary: dict, key: str) -> Any:
try:
return dictionary[key]
except KeyError:
return default_value
# Mal: Estilo LBYL (Look Before You Leap)
def get_value(dictionary: dict, key: str) -> Any:
if key in dictionary:
return dictionary[key]
else:
return default_value
```
## Type Hints
### Anotaciones de Tipo Básicas
```python
from typing import Optional, List, Dict, Any
def process_user(
user_id: str,
data: Dict[str, Any],
active: bool = True
) -> Optional[User]:
"""Procesa un usuario y retorna el User actualizado o None."""
if not active:
return None
return User(user_id, data)
```
### Type Hints Modernos (Python 3.9+)
```python
# Python 3.9+ - Usar tipos built-in
def process_items(items: list[str]) -> dict[str, int]:
return {item: len(item) for item in items}
# Python 3.8 y anteriores - Usar módulo typing
from typing import List, Dict
def process_items(items: List[str]) -> Dict[str, int]:
return {item: len(item) for item in items}
```
### Type Aliases y TypeVar
```python
from typing import TypeVar, Union
# Type alias para tipos complejos
JSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]
def parse_json(data: str) -> JSON:
return json.loads(data)
# Tipos genéricos
T = TypeVar('T')
def first(items: list[T]) -> T | None:
"""Retorna el primer elemento o None si la lista está vacía."""
return items[0] if items else None
```
### Duck Typing Basado en Protocol
```python
from typing import Protocol
class Renderable(Protocol):
def render(self) -> str:
"""Renderiza el objeto a una cadena."""
def render_all(items: list[Renderable]) -> str:
"""Renderiza todos los elementos que implementan el protocolo Renderable."""
return "\n".join(item.render() for item in items)
```
## Patrones de Manejo de Errores
### Manejo de Excepciones Específicas
```python
# Bien: Capturar excepciones específicas
def load_config(path: str) -> Config:
try:
with open(path) as f:
return Config.from_json(f.read())
except FileNotFoundError as e:
raise ConfigError(f"Archivo de config no encontrado: {path}") from e
except json.JSONDecodeError as e:
raise ConfigError(f"JSON inválido en config: {path}") from e
# Mal: except desnudo
def load_config(path: str) -> Config:
try:
with open(path) as f:
return Config.from_json(f.read())
except:
return None # ¡Fallo silencioso!
```
### Encadenamiento de Excepciones
```python
def process_data(data: str) -> Result:
try:
parsed = json.loads(data)
except json.JSONDecodeError as e:
# Encadenar excepciones para preservar el traceback
raise ValueError(f"Error al parsear datos: {data}") from e
```
### Jerarquía de Excepciones Personalizadas
```python
class AppError(Exception):
"""Excepción base para todos los errores de la aplicación."""
pass
class ValidationError(AppError):
"""Se lanza cuando falla la validación de entrada."""
pass
class NotFoundError(AppError):
"""Se lanza cuando no se encuentra un recurso solicitado."""
pass
# Uso
def get_user(user_id: str) -> User:
user = db.find_user(user_id)
if not user:
raise NotFoundError(f"Usuario no encontrado: {user_id}")
return user
```
## Context Managers
### Gestión de Recursos
```python
# Bien: Usar context managers
def process_file(path: str) -> str:
with open(path, 'r') as f:
return f.read()
# Mal: Gestión manual de recursos
def process_file(path: str) -> str:
f = open(path, 'r')
try:
return f.read()
finally:
f.close()
```
### Context Managers Personalizados
```python
from contextlib import contextmanager
@contextmanager
def timer(name: str):
"""Context manager para medir el tiempo de un bloque de código."""
start = time.perf_counter()
yield
elapsed = time.perf_counter() - start
print(f"{name} tardó {elapsed:.4f} segundos")
# Uso
with timer("procesamiento de datos"):
process_large_dataset()
```
### Clases Context Manager
```python
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 # No suprimir excepciones
# Uso
with DatabaseTransaction(conn):
user = conn.create_user(user_data)
conn.create_profile(user.id, profile_data)
```
## Comprehensions y Generadores
### List Comprehensions
```python
# Bien: List comprehension para transformaciones simples
names = [user.name for user in users if user.is_active]
# Mal: Loop manual
names = []
for user in users:
if user.is_active:
names.append(user.name)
# Las comprehensions complejas deben expandirse
# Mal: Demasiado complejo
result = [x * 2 for x in items if x > 0 if x % 2 == 0]
# Bien: Usar una función generadora
def 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
```
### Expresiones Generadoras
```python
# Bien: Generador para evaluación lazy
total = sum(x * x for x in range(1_000_000))
# Mal: Crea una lista intermedia grande
total = sum([x * x for x in range(1_000_000)])
```
### Funciones Generadoras
```python
def read_large_file(path: str) -> Iterator[str]:
"""Lee un archivo grande línea por línea."""
with open(path) as f:
for line in f:
yield line.strip()
# Uso
for line in read_large_file("huge.txt"):
process(line)
```
## Data Classes y Named Tuples
### Data Classes
```python
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
"""Entidad de usuario con __init__, __repr__ y __eq__ automáticos."""
id: str
name: str
email: str
created_at: datetime = field(default_factory=datetime.now)
is_active: bool = True
# Uso
user = User(
id="123",
name="Alice",
email="[email protected]"
)
```
### Data Classes con Validación
```python
@dataclass
class User:
email: str
age: int
def __post_init__(self):
# Validar formato de email
if "@" not in self.email:
raise ValueError(f"Email inválido: {self.email}")
# Validar rango de edad
if self.age < 0 or self.age > 150:
raise ValueError(f"Edad inválida: {self.age}")
```
### Named Tuples
```python
from typing import NamedTupRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.