Dataclass patterns including frozen dataclasses, slots, immutability, and value objects. Activated when designing data classes or value types.
Scanned 2/10/2026
Install via CLI
openskills install majiayu000/claude-skill-registry---
name: dataclass-patterns
description: Dataclass patterns including frozen dataclasses, slots, immutability, and value objects. Activated when designing data classes or value types.
---
# Dataclass patterns
## Purpose
Guide for designing dataclasses including frozen (immutable) dataclasses, slots optimization, validation, and value object patterns.
## When to use
This skill activates when:
- Creating data classes
- Designing immutable value objects
- Optimizing memory usage with slots
- Implementing validation in dataclasses
- Using dataclass features like field factories
## Core patterns
### Frozen immutable dataclass
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Point:
"""Immutable point with memory-efficient slots."""
x: float
y: float
# Usage
p = Point(1.0, 2.0)
# p.x = 3.0 # Raises FrozenInstanceError
```
### With validation
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class PositivePoint:
"""Point with validation."""
x: float
y: float
def __post_init__(self) -> None:
if self.x < 0 or self.y < 0:
raise ValueError(f"Coordinates must be positive: ({self.x}, {self.y})")
```
### With field defaults
```python
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class Config:
"""Configuration with defaults."""
name: str
enabled: bool = True
options: tuple[str, ...] = field(default_factory=tuple)
metadata: dict[str, str] = field(default_factory=dict)
```
## Slots optimization
### Why use slots
```python
# Without slots: each instance has __dict__ for attributes
@dataclass
class RegularPoint:
x: float
y: float
# 120+ bytes per instance
# With slots: fixed attribute storage
@dataclass(slots=True)
class SlottedPoint:
x: float
y: float
# ~50 bytes per instance
```
### Slots with inheritance
```python
@dataclass(slots=True)
class Base:
x: int
@dataclass(slots=True)
class Derived(Base):
y: int
# Python 3.10+ handles slots inheritance correctly
```
## Immutability patterns
### Frozen with copy modification
```python
from dataclasses import dataclass, replace
@dataclass(frozen=True, slots=True)
class User:
id: int
name: str
active: bool
# Modify by creating new instance
user = User(id=1, name="Alice", active=True)
updated = replace(user, active=False)
assert user.active is True
assert updated.active is False
```
### Deeply immutable
```python
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class ImmutableConfig:
"""Deeply immutable config using tuples instead of lists."""
name: str
options: tuple[str, ...] = field(default_factory=tuple)
@classmethod
def from_list(cls, name: str, options: list[str]) -> 'ImmutableConfig':
"""Create from list, converting to tuple."""
return cls(name=name, options=tuple(options))
```
## Field patterns
### Field with factory
```python
from dataclasses import dataclass, field
from datetime import datetime
@dataclass(frozen=True, slots=True)
class Event:
name: str
timestamp: datetime = field(default_factory=datetime.now)
tags: frozenset[str] = field(default_factory=frozenset)
```
### Field with metadata
```python
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class FormField:
name: str
value: str = ""
required: bool = field(default=False, metadata={'form': 'checkbox'})
max_length: int = field(default=100, metadata={'form': 'hidden'})
```
### Exclude from repr/compare
```python
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class CachedResult:
key: str
value: str
# Cache metadata not part of equality or repr
_cache_time: float = field(repr=False, compare=False, default=0.0)
```
## Validation patterns
### Post-init validation
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Range:
start: int
end: int
def __post_init__(self) -> None:
if self.start > self.end:
raise ValueError(f"start ({self.start}) must be <= end ({self.end})")
```
### Factory method validation
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Email:
"""Validated email address."""
address: str
def __post_init__(self) -> None:
if '@' not in self.address:
raise ValueError(f"Invalid email: {self.address}")
@classmethod
def parse(cls, value: str) -> 'Email':
"""Parse and validate email string."""
return cls(address=value.strip().lower())
```
## Comparison and ordering
### Custom ordering
```python
from dataclasses import dataclass
from functools import total_ordering
@total_ordering
@dataclass(frozen=True, slots=True, eq=True)
class Version:
major: int
minor: int
patch: int
def __lt__(self, other: 'Version') -> bool:
return (self.major, self.minor, self.patch) < (other.major, other.minor, other.patch)
```
### Hash for use in sets/dicts
```python
@dataclass(frozen=True, slots=True)
class HashableItem:
"""Frozen dataclass is automatically hashable."""
id: str
name: str
# Can be used in sets and as dict keys
items = {HashableItem("1", "a"), HashableItem("2", "b")}
lookup = {HashableItem("1", "a"): "value"}
```
## Pattern: Value object
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Money:
"""Immutable value object representing money."""
amount: int # In cents to avoid float issues
currency: str
def __post_init__(self) -> None:
if self.amount < 0:
raise ValueError("Amount cannot be negative")
if len(self.currency) != 3:
raise ValueError("Currency must be 3-letter code")
def add(self, other: 'Money') -> 'Money':
if self.currency != other.currency:
raise ValueError("Cannot add different currencies")
return Money(self.amount + other.amount, self.currency)
def __str__(self) -> str:
return f"{self.amount / 100:.2f} {self.currency}"
```
## Checklist
- [ ] Use `frozen=True` for immutable data
- [ ] Use `slots=True` for memory efficiency
- [ ] Validation in `__post_init__` or factory methods
- [ ] Use `tuple`/`frozenset` for immutable collections
- [ ] Use `replace()` for modifications
- [ ] Document invariants
---
**Additional resources:**
- [dataclasses documentation](https://docs.python.org/3/library/dataclasses.html)
No comments yet. Be the first to comment!