I am having trouble setting up a simple dataclass using a new defaultdict(dict).
If I tell the factory to use 'dict' as below , instantiation fails with typerror collection.defaultdict object is not callable
from collections import defaultdict
from dataclasses import dataclass, field
@dataclass
class ResultSet:
changed: bool = False
mqttdata: defaultdict(dict) = field(default_factory=defaultdict(dict)) # does not work!
It does sorta work using field(default_factory=defaultdict) but then my code will fail later when it encounters missing keys - presumably because defaultdict was not set up for dict.
How do I properly set up a new defaultdict(dict) in a dataclass?
You have a few problems with the code and how you are using dataclasses currently:
Type generics in annotations need to be specified through square brackets [] generally, so default[dict] instead of defaultdict(dict) for example.
The default_factory argument to dataclasses.field() needs to be a no-arg callable which returns a new object with default values set. For example, assuming you have a nested dataclass Inner which specifies defaults for all fields, you could use default_factory=Inner to create a new Inner object each time the main dataclass is instantiated.
Note that the default_factory argument is mainly useful for mutable types
such as set, list, and dict, so that the same object isn't
shared (and potentially mutated) between dataclass instances.
Putting it all together, here is the working code which sets a default value for a field of type defaultdict[dict]:
from collections import defaultdict
from dataclasses import dataclass, field
@dataclass
class ResultSet:
changed: bool = False
mqttdata: defaultdict[dict] = field(default_factory=lambda: defaultdict(dict)) # works!
print(ResultSet())
In Python versions earlier than 3.9, which is when PEP 585 was introduced, you'll need to add the following import at the top so that any type annotations are lazy-evaluated:
from __future__ import annotations
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With