DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Dylan Anthony
Dylan Anthony

Posted on • Updated on

You should use Python @dataclass

TL;DR

If you’re using Python 3.7+, dataclasses will save you a bunch of time, make your code cleaner, and maybe even make your code more correct.

Why you should not use a dataclass

  1. πŸ•Έ You’re stuck on a Python version < 3.7. I’m sorry for you, 3.7 adds several really great features, so upgrade whenever you can.
  2. 🚫 There is no 2. If you’re using Python 3.7+ dataclasses will almost certainly help you at some point.

What’s a dataclass?

I’m glad you asked πŸ€“! Python 3.7 added a neat little decorator called @dataclass. Rather than try to explain in English why it’s awesome, I’ll just show you.

What you write

from dataclasses import dataclass, field
from typing import List


@dataclass
class Pizza:
    # Each of these is called a field
    crust: str
    has_cheese: bool = True
    toppings: List[str] = field(default_factory=list)

Enter fullscreen mode Exit fullscreen mode

What you can now do

from dataclasses import asdict, astuple, replace

# An __init__ is created which takes all fields as args or kwargs!
thick_cheesy = Pizza(crust='thick')

# __repr__ is generated, exclude any fields you don’t want
print(thick_cheesy)
# Prints "Pizza(crust='thick', has_cheese=True, toppings=[])"

# Handy method to create a dict, only includes fields
d = asdict(thick_cheesy)
assert d == {
    'crust': 'thick',
    'has_cheese': True,
    'toppings': [],
}

# Create a new object based on another object
with_olives = replace(thick_cheesy, toppings=['olives'])

# Make a tuple from the fields
t = astuple(with_olives)
assert t == ('thick', True, ['olives'])

# __eq__ is generated
assert with_olives != thick_cheesy # Effectively compares as tuples 

Enter fullscreen mode Exit fullscreen mode

But wait, there’s more! πŸ’Έ

With a few options passed to the @dataclass decorator, you can also:

  1. Make your newly formed objects immutable (AKA frozen πŸ₯Ά)
  2. Load additional attributes that don’t show up as fields (aren’t in asdict either!)
  3. Quickly add comparators (<, >, etc.)

Not Sold?

If dataclasses don’t immediately make you excited, why not? I’d love to read your comment.

Top comments (9)

Collapse
 
gergelypolonkai profile image
Gergely Polonkai

How is it different from the attrs package? Other than it’s being builtin?

Collapse
 
dbanty profile image
Dylan Anthony Author

Really nothing other than the fact that it's built in. I've never really used attrs, does it have any features that dataclasses are missing? Or, put another way, is there any reason to use attrs now that the builtin dataclasses are available?

Collapse
 
gergelypolonkai profile image
Gergely Polonkai

I honestly don’t know, i never used either.

Also, it’s not a problem if they are the same… it’s always delightful seeing a community effort included in the standard library. The same happened to unittest and mock (now available as unittest.mock).

Collapse
 
dholth profile image
Daniel Holth

See also the attrs library, which predates @dataclass and works on more versions of Python.

Collapse
 
theodesp profile image
Theofanis Despoudis

This is the same as case classes in Scala or data classes in Kotlin. They reduce boilerplate code and provide some nice features for comparing or serialising objects.

Collapse
 
guin profile image
Angelika Jarosz

Great post, cant wait to experiment with these!

Collapse
 
rakeshsharma14 profile image
rakesh sharma

Cool! reminds me of the data transfer objects in java that's abound in JEE frameworks

Collapse
 
zenulabidin profile image
Ali Sherief

This is coming a little late, but I imagine these would be useful if the class definition is opaque or not readily available.

Collapse
 
mrcartoonster profile image
Evan E. Baird

Why should you use @dataclass??? Because of Strawberry!!!!!!!!!!!!

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.