python-dataclass-fields
Table of Contents
Python dataclass fields
Python dataclass fields (from the dataclasses module) let you declare class attributes declaratively with type hints, default values, and factories. The field() function customizes how attributes behave: mutable defaults via factories, excluding from __repr__, marking as init-only, or running post-initialization logic with __post_init__().
Use dataclasses with fields to reduce boilerplate and make class structure explicit.
Example
This example shows dataclass field configuration and post-init hooks.
# run: python3 dataclass_fields.py # description: dataclass field configuration and post-init from dataclasses import dataclass, field from typing import List # Basic dataclass with defaults @dataclass class Point: x: float = 0.0 y: float = 0.0 p = Point(3.0, 4.0) print(f"Point: {p}") # Mutable default with factory @dataclass class Team: name: str members: List[str] = field(default_factory=list) team1 = Team("A") team1.members.append("Alice") team2 = Team("B") # has separate empty list print(f"Team 1: {team1}") print(f"Team 2: {team2}") # Field configuration @dataclass class Config: name: str password: str = field(repr=False) # hidden in repr debug: bool = field(default=False, init=False) # not in __init__ tags: List[str] = field(default_factory=list, compare=False) # excluded from comparisons config = Config("myapp", "secret123") print(f"Config: {config}") # password not shown print(f"Debug: {config.debug}") # Post-init processing @dataclass class Circle: radius: float area: float = field(init=False) # computed, not initialized def __post_init__(self): """Called after __init__ to compute derived attributes.""" import math self.area = math.pi * self.radius ** 2 circle = Circle(5.0) print(f"Circle: {circle}") print(f"Area: {circle.area:.2f}") # Field with default factory and post-init @dataclass class Database: host: str port: int = 5432 username: str = "admin" password: str = field(repr=False, default="") _connection: object = field(init=False, repr=False, default=None) def __post_init__(self): """Initialize connection after dataclass init.""" self._connection = f"postgres://{self.username}@{self.host}:{self.port}" db = Database("localhost") print(f"Database: {db}") print(f"Connection: {db._connection}") # Field with init=False and default_factory @dataclass class Cache: name: str _data: dict = field(init=False, default_factory=dict) _hits: int = field(init=False, default=0) def get(self, key): if key in self._data: self._hits += 1 return self._data.get(key) def set(self, key, value): self._data[key] = value cache = Cache("mycache") cache.set("key1", "value1") print(f"Cache: {cache}") print(f"Hits: {cache._hits}")
Common patterns
field() parameters:
default: default valuedefault_factory: callable to generate default (for mutable types)init: include in__init__(default True)repr: include in__repr__(default True)compare: include in comparisons (default True)hash: include in__hash__(default is compare value)metadata: arbitrary metadata dict for this field
Mutable defaults:
- Wrong:
items: list = []: shared among all instances - Right:
items: list = field(default_factory=list): separate list per instance - Also works for
dict,set, or any callable
Post-initialization:
__post_init__()called after__init__completes- Use for computed attributes, validation, setup
- Access all initialized attributes here
Init-only fields:
field(init=False): set after init- Useful for derived/computed attributes
- Won't appear in
__init__signature
Excluding from repr:
field(repr=False): hidden from__repr__output- Good for secrets, large objects, internal state
Comparison control:
field(compare=False): ignored in__eq__,__lt__, etc.- Useful for caches, id fields not affecting equality
- By default all fields participate
Field ordering:
- Fields without defaults must come before fields with defaults
field(default=..., ...)counts as “has default”- Fields with
init=Falsecan go anywhere
Field metadata:
field(metadata={'description': '...'}): store arbitrary info- Accessible via
fields()function - Useful for generating docs, validators
Accessing field info:
from dataclasses import fieldsfields(MyClass): returns tuple of Field objectsField.name,Field.type,Field.default, etc.
When to use fields vs simple defaults:
- Use
field()for any mutable default - Use
field()for computed/derived attributes - Simple immutable defaults can use
attr: type = value - Complex initialization use
__post_init__()
python-dataclass-fields.md · Last modified: by 127.0.0.1
