I have a classmethod create_instance() of a dataclass Bar that needs to check on a field(default_factory=...)-type parameter of the dataclass before returning an instance of the dataclass:
from dataclasses import dataclass, field
from typing import Dict
@dataclass
class Bar:
number: int
static_dict: Dict[str, int] = field(
default_factory=lambda: {
'foo': 1,
}
)
@classmethod
def create_instance(cls) -> 'Bar':
access = cls.static_dict
return cls(number=access['foo'])
if __name__ == '__main__':
foo = Bar.static_dict # 1) fails already
foo = Bar.create_instance() # 2) fails too since it uses 1)
This fails with:
AttributeError: type object 'Bar' has no attribute 'static_dict'
Without type-hinting the return value, e.g.
@classmethod
def create_instance(cls):
access = cls.static_dict
return cls(number=access['foo-1'])
if fails by mentioning the dataclass itself doesn't have the attribute:
AttributeError: type object 'Bar' has no attribute 'static_dict'.
The same error would occur using a staticmethod e.g. with type hinting:
@staticmethod
def create_instance_static() -> 'Bar':
access = Bar.static_dict
return Bar(number=access['foo'])
My very ugly workaround is to define a global variable and pass it into the class, which lets me use the create_instance()-method:
from dataclasses import dataclass, field
from typing import Dict
GLOBAL_DICT = {
'foo': 2,
}
@dataclass
class BarWorkaround:
number: int
static_dict: Dict[str, int] = field(
default_factory=lambda: GLOBAL_DICT
)
@classmethod
def create_instance(cls) -> 'BarWorkaround':
access = GLOBAL_DICT
return cls(number=access['foo'])
if __name__ == '__main__':
foo = BarWorkaround.create_instance() # works as intended
Can't say I'm a fan of defining globals for something like this. My guess is something about the way dataclasses are constructed interferes with my accessing the static default attribute, but I don't get what it is.