Circular Dependencies due to Type Hints
With type hints, there are more opportunities for creating circular imports. Fortunately, there is a solution using the special constant: typing.TYPE_CHECKING
.
The following example defines a Vertex
class and an Edge
class. An edge is defined by two vertices and a vertex maintains a list of the adjacent edges to which it belongs.
Without Type Hints, No Error
File: vertex.py
class Vertex:
def __init__(self, label):
self.label = label
self.adjacency_list = []
File: edge.py
class Edge:
def __init__(self, v1, v2):
self.v1 = v1
self.v2 = v2
Type Hints Cause ImportError
ImportError: cannot import name 'Edge' from partially initialized module 'edge' (most likely due to a circular import)
File: vertex.py
from typing import List
from edge import Edge
class Vertex:
def __init__(self, label: str):
self.label = label
self.adjacency_list: List[Edge] = []
File: edge.py
from vertex import Vertex
class Edge:
def __init__(self, v1: Vertex, v2: Vertex):
self.v1 = v1
self.v2 = v2
Solution using TYPE_CHECKING
File: vertex.py
from typing import List, TYPE_CHECKING
if TYPE_CHECKING:
from edge import Edge
class Vertex:
def __init__(self, label: str):
self.label = label
self.adjacency_list: List[Edge] = []
File: edge.py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from vertex import Vertex
class Edge:
def __init__(self, v1: Vertex, v2: Vertex):
self.v1 = v1
self.v2 = v2
Notice the absence of the quotes around the type hints. Because of the postponed evaluation of annotations in Python 3.10, these type hints are treated as if they were in quotes.
Quoted vs. Unquoted Type Hints
In versions of Python prior to 3.10, conditionally imported types must be enclosed in quotes, making them “forward references”, which hides them from the interpreter runtime.
In Python 3.7, 3.8, and 3.9, a workaround is to use the following special import.
from __future__ import annotations
AttributeError
s - it enables looking up the partially initialized module insys.modules
, but doesn't resolve time paradoxes. – Protozoan