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:
- Like the idea of declaring all instance variables in
__init__()
. It gives you an overview of the class contents, and I also hear that some IDEs look into__init__()
for autocompletion information. - Don't want to use type-checker-specific directives in the code to silence this warning, because I want other developers to be free to use their own preferred type checker.
- Don't want to annotate
subject
with something likeAny
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
?