Introduction
attrs is a Python library that removes the boilerplate of writing class infrastructure. By declaring attributes with type annotations or attr.ib() calls, attrs generates init, repr, eq, hash, and other dunder methods automatically. It predates and directly inspired Python's built-in dataclasses module, and remains more feature-rich.
What attrs Does
- Auto-generates init, repr, eq, ne, lt, le, gt, ge, and hash methods
- Validates attribute values at instantiation time using pluggable validators
- Supports default values, factory functions, and optional attributes
- Provides frozen (immutable) classes with slot-based memory optimization
- Integrates with type checkers (mypy, pyright) for full static analysis support
Architecture Overview
attrs uses a class decorator that inspects attribute declarations (type annotations or attr.ib() descriptors) and dynamically generates dunder methods at class creation time. The generated code is compiled once and cached, so runtime overhead is minimal after import. Validators and converters run during init, and the slots=True option uses slots instead of dict for lower memory footprint and faster attribute access.
Self-Hosting & Configuration
- Install from PyPI:
pip install attrs - Use the modern API:
@attrs.definefor mutable classes,@attrs.frozenfor immutable - Legacy API also available:
@attr.swithattr.ib()for explicit field declarations - No configuration files needed; everything is specified in code via decorators and field descriptors
- Works with Python 3.7+ and has zero mandatory dependencies
Key Features
- Two API styles: modern (
@define,@frozen) and classic (@attr.s,attr.ib) for different preferences - Built-in validators:
instance_of,in_,matches_re,min_len, and composable custom validators - Converters that transform input values during initialization (e.g.,
converter=int) - Slot classes by default in the modern API for lower memory usage and faster access
attrs.asdict()andattrs.astuple()for easy serialization to dictionaries and tuples
Comparison with Similar Tools
- dataclasses — stdlib module inspired by attrs; attrs offers validators, converters, slot classes by default, and more field options
- Pydantic — focuses on data validation and parsing from external input (JSON, dicts); attrs is lighter and focused on class boilerplate reduction
- NamedTuple — immutable and lightweight; attrs supports mutability, validators, and richer field configuration
- msgspec — optimized for serialization speed; attrs is more general-purpose for class infrastructure
- cattrs — companion library that adds structured/unstructured serialization on top of attrs classes
FAQ
Q: Should I use attrs or dataclasses? A: For simple data holders, dataclasses is fine. Use attrs when you need validators, converters, slot classes by default, or the richer field API.
Q: Does attrs work with mypy and pyright? A: Yes. attrs ships a mypy plugin and has full PEP 681 support for static type checking with pyright and mypy.
Q: How does attrs affect performance? A: Generated methods are compiled Python bytecode, so attribute access and initialization are as fast as hand-written code. Slot classes are faster than dict-based classes.
Q: Can I use attrs with JSON serialization? A: Use cattrs or attrs.asdict() to convert to dicts, then serialize with json.dumps(). For complex schemas, cattrs provides structured converters.