How To Define Circularly Dependent Data Classes In Python 3.7+?
Solution 1:
There are several ways to solve circular dependencies like this, see Type hints: solve circular dependency
You can always apply the decorator manually (and update the annotations), like @Nearoo's answer shows.
However, it might be easier to "forward declare" the class:
classA:
pass@dataclassclassB:
a: A@dataclassclassA:
b: B
Or simply use a forward reference:
@dataclass
class B:
a: 'A'@dataclass
class A:
b: B
The cleanest is to import Python 4.0's behavior (if you can):
from __future__ import annotations
@dataclassclassB:
a: A@dataclassclassA:
b: B
Solution 2:
You can achieve your goal by applying the dataclass
decorator only after we injected the field b
into A
. For that, we simply have to add the type annotation into A
's __annotations__
-field
The following code solves your problem:
classA:
b: None# Note: __annotations__ only exists if >=1 annotation exists@dataclassclassB:
a: A
A.__annotations__.update(b=B) # Note: not the same as A.b: B
A = dataclass(A) # apply decorator
Concerning the safety and validity of this method, PEP 524 states that
..at the module or class level, if the item being annotated is a simple name, then it and the annotation will be stored in the __annotations__ attribute of that module or class. [This attribute] is writable, so this is permitted:
__annotations__['s'] = str
So adding a type annotation later on by editing __annotations__
is identical to defining it at the class definition.
Solution 3:
As python is script language - there is no way to do it with @dataclass
. Because there is no "autowired" (dependency injection) mechanism in python.
At this moment if you need circular dependency - you should use one of class as regular.
classA:
b = None@dataclassclassB:
a: A
a = A()
a.b = B(a)
Python compiler goes through each line, without jumping from class/function definition. And when compiler/interpreter see following line b: B
and it didn't see B
class before - it will throw an exception NameError: name 'B' is not defined
I would like to believe that there is way to do that(circular dependency for @dataclass
), but the truth is cruel. (There are many things that you can do in Java/other language and can't do in python. Another direction of this statement is truthful either.)
Post a Comment for "How To Define Circularly Dependent Data Classes In Python 3.7+?"