Should you decorate dataclass subclasses if not making additional fields
Asked Answered
M

2

5

If you don't add any more fields to your subclass is there a need to add the @dataclass decorator to it and would it do anything?

If there is no difference, which is the usual convention?

from dataclasses import dataclass

@dataclass
class AAA:
    x: str
    y: str
    
    ...

# decorate?
class BBB(AAA):
    ...
Morly answered 24/11, 2022 at 16:6 Comment(2)
Have you tried it both ways? Could you tell any difference?Cataphyll
Not that I could see.Morly
B
5

From documentation, dataclasses source code and experimenting with class instances, I don't see any difference, even if new fields are added to a subclass1.

If we are talking conventions, then I would advise against decorating a subclass. Class BBB's definition is supposed to say "this class behaves just like AAA, but with these changes" (likely a couple of new methods in your case).

Re-decorating BBB:

  • serves no purpose
  • violates DRY principle: although it's just one line, but still there's no particular difference between re-decorating and copy-pasting a short method from superclass
  • could (potentially) get in the way of changing AAA: you might theoretically switch to another library for dataclassing or decide to use @dataclass with non-default parameters, and that'd require maintaining subclass as well (for no good reason).

Update

1 As Andrius corrected me, if you add new fields in a subclass, you'll encounter the following problem:

>>> class BBB(AAA):
...     z: str
... 
>>> BBB('a', 'b', 'c')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    BBB('a', 'b', 'c')
TypeError: AAA.__init__() takes 3 positional arguments but 4 were given

Original question specifically says that new fields won't be added, so this is just a correction of my initial answer.

Beep answered 26/11, 2022 at 6:2 Comment(2)
Though if you add new fields on subclass, you have to decorate with @dataclass. Because you will get error like Base.__init__() got an unexpected keyword argument 'new_field' (Base is base dataclass and `new_field is some new field on subclass), when trying to instantiate subclass.Got
@Andrius, you're totally right. For some reason I was sure I had checked it back in 2022, but apparently not: it's unlikely that this behaviour has changed between Python versions. I've updated my answer, thanks for the heads-up!Radcliff
S
1

If you don't decorate your class, the variables defined in the root of the class will be class attributes which would be shared between all instances of the class. The dataclass let's you define the variables there but they would be instance attributes so each instance can hold its own value. If you instantiate only a single object, you won't see the difference.

UPDATE

Misunderstood your question. The decorate "adds" a few methods to your class, such as __init__ and __repr__. If you're not adding any attributes to your child class, then adding the decorator just instructs the interpreter to go through the MRO to update the mapping, which hasn't changed. It will not cause any trouble, it's just unnecessary. I haven't seen any well-defined convention for it but I wouldn't do it.

Spiros answered 24/11, 2022 at 16:25 Comment(1)
I'm not asking about whether or not to decorate base class A (it will be decorated as a dataclass). But about any of its subclassesMorly

© 2022 - 2025 — McMap. All rights reserved.