Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define circularly dependent data classes in Python 3.7+?

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?

like image 222
Naetmul Avatar asked Oct 06 '18 07:10

Naetmul


People also ask

How do you initialize a data class in Python?

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.

What is @dataclass in Python?

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.

How does Dataclass work in Python?

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.

Can Python DataClasses have methods?

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.


1 Answers

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
like image 59
Acorn Avatar answered Oct 15 '22 06:10

Acorn