Pylance autocompletion with subclasses

Question:

The problem is that in the following situation, autocompletion in the SubFoo class does not work in Pylance. Pylance only recognize the methods and attributes of the Bar class inside SubFoo class, but not the methods and attributes of the SubBar class. Am I doing the right thing?

class Bar:

    def method1(self):
        # do stuff


class SubBar(Bar):

   def method2(self):
       # do stuff


class Foo:

    def __init__(self, arg: Bar):
        self.attr: Bar = arg

    def do_a(self):
       self.attr.method1()


class SubFoo(Foo):

    def __init__(self, arg: SubBar):
        super().__init__(arg)
 
    def do_b(self):
       self.attr.method1() # Pylance's autocopmletion recognizes method1()
       self.attr.method2() # Pylance's autocopmletion doesn't recognize method2()
Asked By: Stimpy

||

Answers:

You’ve declared the type of Foo.attr to be Bar. The fact that it happens to be assigned a SubBar at some point is not the type checker’s concern. If you want to statically know the type of the field based on the subclass, then Foo should be generic.

from typing import TypeVar, Generic

_T = TypeVar("_T", bound=Bar)

class Foo(Generic[_T]):

    def __init__(self, arg: _T):
        self.attr: _T = arg

    def do_a(self):
       self.attr.method1()


class SubFoo(Foo[SubBar]):

    def __init__(self, arg: SubBar):
        super().__init__(arg)
 
    def do_b(self):
       ...

Now subclasses of Foo are required to report which subclass of Bar they expect their constructor to receive, and that type information becomes available statically.

You’ll also want to consider making that type variable covariant, if your use case supports it.

Answered By: Silvio Mayolo
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.