loading...

You should use Python @dataclass

dbanty profile image Dylan Anthony Updated on ・2 min read

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)

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 

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.

Posted on by:

dbanty profile

Dylan Anthony

@dbanty

Backend Dev obsessed with security

Discussion

markdown guide
 

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

 

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?

 

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).

 

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

 

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.

 

Great post, cant wait to experiment with these!

 

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

 

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

 

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