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()
CodePudding user response:
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.