I am trying to provide type hints for a class init method, that uses child classes of a specific base class. Gooling how to do this tells me to use Type[BaseClass]
as annotation, however inspections keep telling me i'm wrong.
As an example for my problem, let's say this is base.py
:
class B:
def __init__(self):
return
..and another class.py
...
class SomeClass:
def __init__(self, some_param: Type[B]):
self.sp = some_param
Now, using these classes in the following way in a third file test.py
brings forth some confusion for me:
from base import B
from class import SomeClass
if __name__ == '__main__':
sc = SomeClass(B())
I would have guessed this to be correct, yet the pycharm inspections underline it with the hint:
Excpected type 'Type[B]', got 'B' instead
So since this didn't work, I figured I might need to use a TypeVar
, so I changed base.py
to:
class B:
def __init__(self):
return
TB = TypeVar('TB', bound=B)
and class.py
to:
class SomeClass:
def __init__(self, some_param: Type[TB]):
self.sp = some_param
However, this merely changes the pycharm inspection to say:
Excpected type 'Type[TB]', got 'B' instead
Finally, if I set class.py
to:
class SomeClass:
TB = TypeVar('TB', bound=B)
def __init__(self, some_param: Type[TB]):
self.sp = some_param
The inspection error in test.py
is gone and there are no complaints from pycharm!
(Curiously though, there are still complaints if I move if __name__ == '__main__': sc = SomeClass(B())
to class.py
.)
As I said I'm a bit puzzled as to how to truly use base classes with typing in Python:
If not,
Type[B]
not enough/working?TypeVar
within the class and can't simply import the TypeVar
?Type[B]
is for indication that the argument should be a class object itself.
For example,
class A:
pass
class B:
pass
class C(B):
pass
def foo(x: Type[B]):
pass
foo(A) # fails
foo(B) # passes
foo(C) # passes
foo(B()) # fails - an instance of B is not B or a subclass of B
You just want B
as the type hint, to allow an instance of B
(or a subclass of B
) as an argument.
class SomeClass:
def __init__(self, some_param: B):
self.sp = some_param