I've been reading through PEP484 and 526 and still can't figure out what is a better way to do type annotations for variables without an initial value.
Say, you have a class and in the __init__ you want to declare a variable, but without providing an initial value where assignment happens later in the code. Usually what I would normally do is:
from typing import Optional, List
class SomeClass:
def __init__(self) -> None:
self.some_value: Optional[int] = None
self.other_var: Optional[List] = None
def _some_method(self) -> None:
self.some_value = 42
This works, but I feel like using Optional makes __init__ overly busy and harder to read. Instead what I could do is:
from typing import List
class SomeClass:
def __init__(self) -> None:
self.some_value: int
self.other_var: List
def _some_method(self) -> None:
self.some_value = 42
Obviously, this leaves variables uninitialized, but as long as they are correctly assigned to before being referenced, everything works just fine and makes it easier to read if I have a lot of class attributes declared in __init__.
Are there any specific issues that could arise from leaving variables uninitialized when using the second approach?
Are there any specific issues that could arise from leaving variables uninitialized when using the second approach?
Yes. Adding type annotations without setting a value is for the type checker only. You won't actually create the variable. Just have a look at the error thrown from your second example:
from typing import List
class SomeClass:
def __init__(self) -> None:
self.some_value: int
self.other_var: List
def _some_method(self) -> None:
self.some_value = 42
sc = SomeClass()
print(sc.some_value)
Traceback (most recent call last):
File ".../test.py", line 14, in <module>
print(sc.some_value)
^^^^^^^^^^^^^
AttributeError: 'SomeClass' object has no attribute 'some_value'
Note that the error is "has no attribute". In other words, the attribute was not created at all.
As of Python 3.10 the syntax has gotten a little cleaner, so you don't need the import from typing anymore, and you don't need Optional anymore. This is how I'd type your class:
class SomeClass:
def __init__(self) -> None:
self.some_value: int | None = None
self.other_var: list[int] | None = None
def _some_method(self) -> None:
self.some_value = 42
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With