Suppose that class A
has a member whose type is class B
, and class B
has a member whose type is class A
.
In Scala or Kotlin, you can define the classes in any order without worries in this case because the firstly-defined class can use the secondly-defined class as usual, even in case/data classes.
However in Python, the following code
class A:
b = B()
class B:
a = A()
throws a compile error because class B
is not defined when class A
is being defined.
You can work around this simple case, like in this answer
class A:
pass
class B:
a = A()
A.b = B()
However, this way does not work for data classes in Python because assigning members after the definition of data classes will not update the auto-generated methods of the data classes, which makes the usage of "data class" useless.
@dataclass
class A:
b: B # or `b: Optional[B]`
@dataclass
class B:
a: A # or `a: Optional[A]`
How can I avoid this problem?
A Python class is a program used to create objects and their properties. We use the keyword class to create a class in Python. For class attributes to be initialized, we use a constructor method called __init__() which is called when an object is created in a Python class.
Python introduced the dataclass in version 3.7 (PEP 557). The dataclass allows you to define classes with less code and more functionality out of the box. The following defines a regular Person class with two instance attributes name and age : class Person: def __init__(self, name, age): self.name = name self.age = age.
DataClass in Python DataClasses are like normal classes in Python, but they have some basic functions like instantiation, comparing, and printing the classes already implemented. Parameters: init: If true __init__() method will be generated. repr: If true __repr__() method will be generated.
A dataclass can very well have regular instance and class methods. Dataclasses were introduced from Python version 3.7. For Python versions below 3.7, it has to be installed as a library.
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:
class A:
pass
@dataclass
class B:
a: A
@dataclass
class A:
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
@dataclass
class B:
a: A
@dataclass
class A:
b: B
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