Well I only just noticed that since Python 3.11, there’s this slots
option built-in to dataclass
already so at least your specific use case has been taken care of:
from enum import Enum
from dataclasses import dataclass
from typing import Literal
@dataclass(slots=True)
class Card:
value_: Literal[2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
suite: Literal['heart', 'diamond', 'club', 'spade']
class PlayingCards(Card, Enum):
TWO_OF_HEART = 2, 'heart'
THREE_OF_SPADES = 3, 'spade'
print(PlayingCards.__slots__) # outputs ('value_', 'suite')
PlayingCards.TWO_OF_HEART.value.name = 'foo' # raises AttributeError
However, it has to be said that there never was a good reason IMHO for dataclass
to be a class decorator to begin with if not for fear of a metaclass conflict. People have to use awkward workarounds to get __init_subclass__
to see dataclass fields, for example, only because dataclass
is a decorator and not a metaclass-driven class.
Bottom Line
Reducing metaclass conflicts with a built-in resolution/merging mechanism will encourage developers to make better design choices without fear of affecting user experience.