I've been wondering what's the most pythonic way and also most readable way to declare a variable's type without directly assigning a value in Python 3.11
Given a class
class MyClass:
def __init__(self, value: str):
self.value: str = value
I could declare the variable without assigning a value:
def test():
variable: MyClass
if True:
variable = MyClass(value="value")
else:
variable = MyClass(value="otherValue")
That would work but the variable is non existant when trying to use it so it's there just for readability.
I could use Optional
def test():
variable: Optional[MyClass] = None
if True:
variable = MyClass(value="value")
else:
variable = MyClass(value="otherValue")
assert isinstance(variable, MyClass)
Or I could type it on first use
def test():
if True:
variable: MyClass = MyClass(value="value")
else:
variable = MyClass(value="otherValue")
I couldn't find anything in Peps, chatGpt4 is contradicting itself, and google sends me to 2015 GitHub's questions. The tool MyPy seems to be fine with the three of them, but I wonder, is there a "correct" way ?
Thank you!
Ok, by parsing Pep again here's what I found:
In stubs it may be useful to declare the existence of a variable without giving it an initial value. This can be done using PEP 526 variable annotation syntax:
from typing import IO stream: IO[str]
The above syntax is acceptable in stubs for all versions of Python. However, in non-stub code for versions of Python 3.5 and earlier there is a special case:
from typing import IO stream = None # type: IO[str]
Type checkers should not complain about this (despite the value None not matching the given type), nor should they change the inferred type to Optional[...] (despite the rule that does this for annotated arguments with a default value of None). The assumption here is that other code will ensure that the variable is given a value of the proper type, and all uses can assume that the variable has the given type.
So the "correct" way seems to be
def test():
variable = None # type: MyClass
if True:
variable = MyClass(value="value")
else:
variable = MyClass(value="otherValue")
So it seems we're still using comments as a way of typing which I'm personally not a big fan of.
Edit: As noted by InSync in the comment, I did not read correctly, the comment is needed for python 3.5 and earlier. So this version seems to be the one recommended
from typing import IO
stream: IO[str]