skip to Main Content

I need type hints for the sake of autocomplete in VSCODE. I have following:

# a.py

class A:
    def __init__(self):
        self.B = B(self)
# b.py

from a import A
# I NEED TO IMPORT A HERE SO I CAN REFER TO A IN TYPE HINT

class B:
    def __init__(self, a: A):
        self.A = a

This causes circular import. I have read, that it is allowed to type hint in between single quotation marks, but this removes the purpose for why I need it. It is VSCODE autocomplete. Once A is in quotation marks, VSCODE does not know what it is. I have read about stub files, but these wont work for me, because I would have to edit these files every time I change A class and I plan to have it a large class.

2

Answers


  1. I think TYPE_CHECKING will solve the problem of your circular import.

    Try import as in the following code.

    from typing import TYPE_CHECKING
    
    if TYPE_CHECKING:
        from a import A
    

    The following article may also be helpful for your understanding.
    Python type hinting without cyclic imports

    Login or Signup to reply.
  2. If you have the following files.

    a.py

    from b import B
    
    class A:
        def __init__(self) -> None:
            self.b = B(self)
    

    b.py

    import typing
    
    if typing.TYPE_CHECKING:
        from a import A
        
    class B:
        def __init__(self, a: "A"):
            self.a = a
            
    # actual usage
    def foo() -> None:
        B(1)
    

    mypy will return b.py:11: error: Argument 1 to "B" has incompatible type "int"; expected "A" [arg-type]

    Depending on the linter you use, you may also get this information in your IDE. For me I get a listing error

    Argument of type "Literal[1]" cannot be assigned to parameter "a" of type "A" in function "__init__" "Literal[1]" is incompatible with "A"Pylance
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search