Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk6 min

How to Use @dataclass in Python

A practical guide to Python's @dataclass decorator: generated methods, field defaults, default_factory, keyword-only fields, the main options, and helper functions such as asdict(), astuple(), and replace().
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Import dataclass from dataclasses, place @dataclass directly above a class, and list each field as an annotated class attribute. Python then generates the boilerplate you would otherwise write by hand: an __init__ method, a readable __repr__, and an __eq__ method. The remaining decisions concern defaults, which methods to generate, and whether instances may change after creation.

What the decorator generates

The decorator reads the annotated class variables in the class body and treats each one as a field. It then adds special methods based on those fields. It does not wrap the class or return a replacement; the class you decorated is the class you get back.

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

point = Point(2.0, 3.5)
print(point)        # Point(x=2.0, y=3.5)
print(point == Point(2.0, 3.5))  # True

With no arguments, @dataclass generates __init__, __repr__, and __eq__. Generated equality only returns true when both objects have the identical type, so a Point never equals a subclass instance with the same values.

Equality changed in Python 3.13. Earlier versions compared tuples of field values; Python 3.13 compares fields individually. For most code the results match, but edge cases such as values that behave unusually under equality (NaN is the classic example) can differ. If your code depends on that behavior, pin the target version and test on it. The official reference is the Python 3.13 dataclasses documentation.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Annotations are not runtime type checks. A field declared x: float will still accept a string if a caller passes one. Two special annotations change how a class variable is treated. ClassVar marks shared class-level data that is not a field. InitVar marks a value that is passed to __init__ and forwarded to __post_init__() but not stored as an attribute.

Declaring fields and defaults

Simple defaults

Assign a default in the class body for immutable values such as numbers, strings, tuples, and None:

@dataclass
class Server:
    host: str
    port: int = 8080
    debug: bool = False

Fields with defaults can be omitted when calling the class: Server("localhost") sets port to 8080.

Per-instance defaults with default_factory

Do not use a mutable object such as a list or dictionary as a plain default. Every instance would share the same object. Use field(default_factory=...) so each instance receives a newly created value:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from dataclasses import dataclass, field

@dataclass
class Inventory:
    name: str
    items: list[str] = field(default_factory=list)

a = Inventory("front")
b = Inventory("back")
a.items.append("tape")
print(b.items)  # []

Controlling individual fields with field()

field() accepts options that change how one field behaves:

  • init=False keeps the field out of the generated __init__. Use it for values computed in __post_init__().
  • repr=False hides the field from the generated __repr__, which helps with secrets or large data.
  • compare=False excludes the field from generated equality and ordering comparisons.
  • hash= controls whether the field takes part in the generated __hash__.
  • metadata stores a mapping that third-party tools can read.
  • kw_only=True makes the field keyword-only.

Ordering of required and default fields

A field without a default cannot come after a field with a default in the generated initializer. This rule also applies to fields inherited from a dataclass base class. Breaking it raises a TypeError when the class is defined:

@dataclass
class Bad:
    x: int = 0
    y: int        # TypeError: non-default argument 'y' follows default argument

Reorder the fields, or make the earlier field keyword-only.

Keyword-only fields

To force callers to pass a field by name, mark it with field(kw_only=True), or insert a KW_ONLY sentinel so that every later field is keyword-only:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from dataclasses import dataclass, KW_ONLY

@dataclass
class Request:
    url: str
    _: KW_ONLY
    timeout: float = 5.0
    retries: int = 3

Request("https://example.com", timeout=2.0)

Keyword-only fields are not included in __match_args__, so they cannot be matched by position in a match statement.

Decorator options

The decorator accepts keyword arguments that switch individual methods on or off. The table lists the defaults and the Python version notes stated in the Python 3.13 reference.

Option Default Effect Version note
init True Generates __init__ unless the class already defines one. Not stated in the Python 3.13 reference
repr True Generates a readable __repr__ unless one already exists. Not stated in the Python 3.13 reference
eq True Generates __eq__ comparing fields; requires identical instance types. Comparison method changed in Python 3.13
order False Generates the four ordering methods. Requires eq=True. Not stated in the Python 3.13 reference
frozen False Raises FrozenInstanceError on assignment or deletion of fields. Not stated in the Python 3.13 reference
unsafe_hash False Forces generation of __hash__. By default hashing follows the eq and frozen combination. Not stated in the Python 3.13 reference
match_args True Generates __match_args__ from positional, non-keyword-only initializer parameters. Not stated in the Python 3.13 reference
kw_only False Makes every field keyword-only. Added in Python 3.10
slots False Generates __slots__ for the class. Added in Python 3.10
weakref_slot False Adds a slot that allows weak references. Requires slots=True. Added in Python 3.11

frozen=True

@dataclass(frozen=True)
class Config:
    host: str
    port: int = 8080

c = Config("localhost")
c.port = 9000   # raises FrozenInstanceError

A frozen dataclass prevents ordinary attribute assignment, but it is not truly immutable. The generated initializer must set fields through object.__setattr__, which adds a small performance cost during construction. Code can also call object.__setattr__ directly to change a field, so treat frozen=True as a guard against accidental mutation rather than a security boundary.

When eq=True and frozen=True are both set, the class gets a generated __hash__, so its instances can be used in sets and as dictionary keys. Frozen instances are the usual choice for value objects.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

order=True

@dataclass(order=True)
class Version:
    major: int
    minor: int

print(Version(1, 4) < Version(2, 0))  # True

Ordering compares the fields in declaration order, as tuples. Use it only when that sequence is a meaningful sort key. A field such as a free-text note should be excluded with field(compare=False).

slots=True

@dataclass(slots=True)
class Sample:
    value: int

s = Sample(3)
s.extra = 1   # AttributeError: no __dict__ on slotted instances

Slotted instances store fields in fixed slots rather than a per-instance __dict__. This reduces memory use and blocks accidental new attributes. It also means the class cannot be given attributes it did not declare. Add weakref_slot=True only when you need weakref.ref() to work on instances, and remember that it requires Python 3.11 or later.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Helper functions

fields() and the shape of a field

fields(obj_or_class) returns a tuple of field descriptors, each with name, type, and default attributes. ClassVar and InitVar pseudo-fields are excluded. The result is useful for generic code such as serializers:

from dataclasses import fields

[f.name for f in fields(point)]  # ['x', 'y']

asdict() and astuple()

asdict() converts an instance into a dictionary, and astuple() converts it into a tuple. Both recurse into nested dataclasses, lists, tuples, and dictionaries. Other values are deep-copied, so the result does not share mutable objects with the original.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from dataclasses import asdict, astuple

asdict(point)   # {'x': 2.0, 'y': 3.5}
astuple(point)  # (2.0, 3.5)

If you only need a shallow dictionary of top-level fields, build it from fields() and getattr():

{f.name: getattr(point, f.name) for f in fields(point)}

replace()

replace() creates a new instance with some fields changed. It calls the class initializer, so __post_init__() runs again. Fields declared with init=False cannot be passed as changes, and doing so raises an error.

from dataclasses import replace

moved = replace(point, x=5.0)  # Point(x=5.0, y=3.5)

This is the usual way to “update” a frozen dataclass, because the original instance cannot be modified.

Choosing options

  • Plain data holder with mutable state: use the default settings and add default_factory for mutable defaults.
  • Value object that should not change: use frozen=True, and update it with replace().
  • Objects that must be sorted: add order=True only after confirming that field order is the intended sort key, and exclude fields that should not affect comparison.
  • Many instances or call sites where argument order is error-prone: use kw_only=True on the class or individual fields. Remember that this requires Python 3.10 or later.
  • Memory-sensitive code that does not need dynamic attributes: use slots=True, and check that no code relies on __dict__.
  • Code that must run on older interpreters: check the version column above before using kw_only, slots, or weakref_slot, and avoid depending on equality internals if you support both Python 3.12 and 3.13.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.