I have 2 class (that are defined in two different package).
An A object as a "set" of B objects that all refer to the said A object.
Here is how it looks like :
the a.py :
from b import B
class A():
def __init__(self, data):
self.data = data
self.Bs = {}
def add_B(self, id, data_B):
self.Bs[id] = B(data_B, self)
the b.py :
class B():
def __init__(self, data, a_instance):
self.data = data
self.a = a_instance
so everything works preety good, but I'd like to hint python that the a_instance
is indeed a class A object to have autocompletion in visual studio code.
At first i've tried to add from a import A
and modify def __init__(self, data, a_instance : A):
in the b.py file, but i've obviously got a circular import error
So I've been trying to use the typing
package, and so added those lines to the a.py file :
from typing import NewType
A_type = NewType('A_type', A)
But I'm steel getting a circular import error.
Can Anyone explain me what I'm doing wrong ?
thanks for the help
PS: My classes actually have some complex methods and are defined in _a.py (resp. _b.py) and the __init__.py
just import the class A and declare the A_type
(resp. just import the class B)
CodePudding user response:
Use
typing.TYPE_CHECKING
, a variable that's never true at runtime- the string form of a type annotation to refer to a name that is not in scope at runtime:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from a import A
class B:
def __init__(self, data, a_instance: "A"):
...
However, if you can restructure your code in a way that avoids circular imports altogether, all the better.
CodePudding user response:
You could try an abstract class with attributes of A and B, then implement each accordingly.
from collections.abc import abstractmethod, ABCMeta
class ABInerface(metaclass=ABCMeta):
@property
@abstractmethod
def data(self):
pass
@data.setter
@abstractmethod
def data(self, value):
pass
@property
@abstractmethod
def Bs(self):
pass
@Bs.setter
@abstractmethod
def Bs(self, value):
pass
@property
@abstractmethod
def a(self):
pass
@a.setter
@abstractmethod
def a(self, value):
pass
@abstractmethod
def add_B(self, id, data_B):
pass
Then, create each class by extending the Interface meta class.
class B(ABInerface):
def __init__(self, data, a_instance):
self.data = data
self.a = a_instance
class A(ABInerface):
def __init__(self, data):
self.data = data
def add_B(self, id, data_B):
self.Bs[_id] = B(data_B, self)