In my app there are many cases of classes that essentially behave like this:
class A:
def __init__(self) -> None:
self.subject = None
def set_subject(self, subject: SpecificClass) -> None:
self.subject = subject
def do_something_with_subject(self) -> None:
self.subject.do_stuff()
It's an invariant of the program that do_something_with_subject()
is always called after set_subject()
, but I must create class A
before I know what to set the subject to, so right now I'm setting default values in __init__()
. In the case of subject
, the only logical default value is None
.
Now for the problem: my static type checker (pyright) complains about self.subject.do_stuff()
. Since it sees in __init__()
that subject
can be None
, it tells me that do_stuff()
is not a member of None
. All very reasonable, except that this is not a warning I wish to see, given how my program operates. I also:
__init__()
. It gives you an overview of the class contents, and I also hear that some IDEs look into __init__()
for autocompletion information.subject
with something like Any
that excludes it from the type checking.Is there some way I can have my cake and eat it too in this case? Keep subject
under type checking scrutiny, keep it somehow declared in __init__()
, and not have the type checker think it can be None
?
This can be achieved by using cast
.
self.subject = cast(SpecificClass, None)
will return the value (None
) unchanged, but will signal to the type checker that it has a specific type (SpecificClass
).