Reputation: 666
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?
Upvotes: 20
Views: 20698
Reputation: 11642
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
Upvotes: 28