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.
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}")
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 fieldMutable defaults:
items: list = []: shared among all instancesitems: list = field(default_factory=list): separate list per instancedict, set, or any callablePost-initialization:
__post_init__() called after __init__ completesInit-only fields:
field(init=False): set after init__init__ signatureExcluding from repr:
field(repr=False): hidden from __repr__ outputComparison control:
field(compare=False): ignored in __eq__, __lt__, etc.Field ordering:
field(default=..., ...) counts as “has default”init=False can go anywhereField metadata:
field(metadata={'description': '...'}): store arbitrary infofields() functionAccessing 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:
field() for any mutable defaultfield() for computed/derived attributesattr: type = value__post_init__()