3 ms·
Would switching all classes to the data class style mean losing the ability to differentiate between class variables and object variables? I'm going to go try
by dec0dedab0de 4y ago
Would switching all classes to the data class style mean losing the ability to differentiate between class variables and object variables?
I'm going to go try it in a minute, but I'm specifically thinking of setting a mutable variable to use as a way to cache the results of a long running process across objects. Or even just any variable to use with class methods. I'll update soon
edit:
I tried it out and it looks like it works just fine
@dataclass
class MyCoolDataClass:
arg: any
_things = {'last_updated':0, 'data':[]}
_things_timeout = 300
def _update_things(self):
"""some long process"""
time.sleep(10)
self._things['last_updated'] = time.time()
self._things['data'] = ['some things']
@property
def things(self):
seconds_since = time.time() - self._things.get('last_updated', 0)
if seconds_since >= self._things_timeout:
self._update_things()
return self._things.get('data',[])
which then works as expected, sharing the cache between objects.
start_time = time.time()
for i in range(10):
obj = MyCoolDataClass(i)
print(obj.things, int(time.time() - start_time))
['some things'] 10
['some things'] 10
...
So yeah, I think I might be on board with dataclasses by default. As long as we can still add __init__ for when we want to do something extra with the variable
edit2:
If we switch to dataclasses things like this would need to raise a syntax error:
@dataclass
class MyOtherDataClass:
arg: any
def __init__(self, special_arg:str):
self.special_arg = special_arg.lower().strip()
As it stands now defining __init__ completely removes any definitions set in the class.
I think the killer feature would be if we added django forms style validate methods for validation and normalization. imagine if we could do this:
class Drink:
temp: str
container: str
def _validate_temp(self, temp):
temp = temp.strip().lower()
if temp not in ['hot', 'cold', 'room']:
raise ValidationError(f'"{temp}" is not a valid temperature')
return temp
def _validate_container(self, container):
container = temp.strip().lower()
if container not in ['mug', 'glass' 'sippy cup']:
raise ValidationError(f'"{container} is not a valid container")
return container
def _validate(self, kwargs):
if kwargs['temp'] == 'cold' and kwargs['container'] == 'mug':
raise ValidationError("Don't dirty a mug for a cold drink!")
Sure, it goes against explicit is better than implicit, but that could be fixed with decorators. It would also be nice to have a concise way to say what values are valid, and a handful of standard normalization processes, but I think you get the idea.
- atorodius 4y agotypically only things that you annotate end up instance variablses for dataclasses