Let’s say I have such structure with @dataclass
from dataclasses import dataclass, field from dataclasses_json import dataclass_json @dataclass_json @dataclass() class Direction: x: int y: int z: int @dataclass_json @dataclass() class Movement: speed: int direction: Direction = field(default_factory=Direction) movementDict = {'speed':2,'direction': {'x':0,'y':0,'z':1}} movement = Movement.from_dict(movementDict) print(movement)
It does what I want – transfering raw dictionary into class object. However I am forced to make Direction class on top of the file. It would be more readable if Movement class was on top of the code. Is there any way to achieve this? If I switch both these classes I get
NameError: name ‘Direction’ is not defined
Advertisement
Answer
One option could be to create a lambda
and pass it as the default_factory
argument. I would also either add a from __future__ import annotations
import at the top, or else wrap the annotation for the forward-declared class in a string, just so the compiler doesn’t complain about a similar NameError in this case.
This works because the type (Direction) is only evaluated once the lambda is actually called. If you don’t believe me, you can also try making an intentional typo in the name – for example like lambda: Drection(0, 0, 0)
and will note that the code still compiles fine even though that name is not defined, as long as your input dict
object has a value for the ‘direction’ key.
Here’s an example to illustrate that below:
from dataclasses import dataclass, field from dataclasses_json import dataclass_json @dataclass_json @dataclass() class Movement: speed: int direction: 'Direction' = field(default_factory=lambda: Direction(0, 0, 0)) @dataclass_json @dataclass() class Direction: x: int y: int z: int movementDict = {'speed': 2} movement = Movement.from_dict(movementDict) print(movement)
Result:
Movement(speed=2, direction=Direction(x=0, y=0, z=0))
Side note: just adding a plug here to a very similar de-serialization library I’ve been working on, called the dataclass-wizard. It has pretty minimal dependencies, and performs a little better on average, in case anyone is curious and wants to check it out.