Why doesn't Python raise a TypeError when type annotations are absent in dataclass subclasses?"

I ran into this subclassing dataclasses for the first time. Could not understand what I was missing. What is the rationale of this not raising a syntax error?

from dataclasses import dataclass

@dataclass
class Base:
    value: int = 10

@dataclass
class Subclass(Base):
    value = 20  # missing the `: int`

# Example usage
base_instance = Base()
print(base_instance.value)  # Output: 10

subclass_instance = Subclass()
print(subclass_instance.value)  # Output: 10

Are there any intended use cases where this behavior is desirable? Additionally, are there any recommended practices or alternative approaches to enforce stricter attribute overwriting in dataclass subclasses when required?

1 Like

dataclass.field() will raise a TypeError:

value = field(default=20)

TypeError: 'value' is a field but has no type annotation

So maybe that’s a good way of avoiding this in the future?

A field is defined as a class variable with a type annotation, but dataclasses are not forbidden from having other class variables, right?

Subclass has removed the field from Base and used the name for a class attribute. Subclass(10) fails with an exception because it’s not a valid argument.

1 Like

Thanks, the ‘class variable’ vs ‘instance variable’ surprised me a bit and I’ll be sure to watch out for it in the future!

from dataclasses import dataclass

@dataclass
class Base:
    value: int = 10

@dataclass
class Subclass(Base):
    value = 20
# Should be `value: int = 20`. missing the `: int`.
# It's treated as a Class level variable and will be
# overwritten by Base `value` during init

print(Base().value) # Output: 10
print(Subclass.value) # Output: 20
print(Subclass().value)  # Output: 10
1 Like

Oh that’s weirder than I thought :joy: It overrides the signature of the init method but still sets the default…