I have a dataclass, it carries an
INITIALIZED state, and I only want to have users to access it if it’s in INITIALIZED state. The way that’s implemented at the moment is:
@dataclass class MyControlledDataclass: _INITIALIZED: bool = False RANDOM_ATTR: str = "random" def __getattribute__(self, key): print("Im getting an attribute") # Line 7 if not self._INITIALIZED: raise Exception("This class was not initialized") try: return getattr(self, key) except KeyError: print("Couldn't find Key!") raise AttributeError(key) def __getitem__(self, key): print("Im getting an item") is_initialized = getattr(self, "_INITIALIZED") if not is_initialized: raise Exception("initialized") try: return getattr(self, key) except KeyError: print("Couldn't find Key!") raise AttributeError(key)
And then I actually Initialize the object like:
controlled_class = MyControlledDataclass() # After going through the initializer I set `_INITITLIZED=True` initializer(controlled_class)
And now, if I want to get an item, like
controlled_class.RANDOM_ATTR I would expect this to go through the
__getattribute__ method, so it can first check whether this was actually initialized or not.
No if I set the breakpoint at line 7 (the print on
__getattribute__), before I move to line 8, the console already shows the recursion, and “im getting an attribute” has already printed multiple times (recursion limit). So I’m lost on what exactly is happening. Shouldn’t I be able to control the access through the
__getattribute__? It seems to run even before I move to the next line. The same thing happens with
# With _INITILIZED = True # This should work normally "random" == controlled_class.RANDOM_ATTR # With _INITILIZED = False # This should raise a custom Exception saying the class was not Initialized controlled_class.RANDOM_ATTR # With _INITILIZED = True # This should raise an AttributeError (it is initialized, but the key doesn't exist) controlled_class.DONT_EXIST
I could use
@property all around, but I have over 100 items, so not really optimal.
Ideas on what I might be doing wrong? Or workarounds?
I’m on Python 3.10.6