This is a question about best practice – consider I have the following base class module, base.py
:
from __future__ import annotations
from typing import TYPE_CHECKING
if type_checking:
from redis import Redis
class Base:
redis: Redis
def __init__(self, redis):
self.redis = redis
Assuming I want a class that inherits from Base
– which of the following is considered better and why? Is there another way I didn’t think of?
(1.) seems cleaner but in (2.) I declare redis: Redis
explicitly, which might be better for type-checking tools
1.
from base import Base
class Sub(Base):
user_id: int
def __init__(self, redis, user_id):
super().__init__(redis)
self.user_id = user_id
from __future__ import annotations
from typing import TYPE_CHECKING
from base import Base
if TYPE_CHECKING:
from redis import Redis
class Sub(Base):
redis: Redis
user_id: int
def __init__(self, redis, user_id):
super().__init__(redis)
self.user_id = user_id
2
Answers
As @deceze mentioned, type-checking tools should understand your inheritance model and handle the hint appropriately.
In terms of "best practices", your option 1 is perfectly fine since you don’t have to re-declare
redis
.If you want something cleaner, another option is to use
dataclasses
Reference docs: https://docs.python.org/3/library/dataclasses.html
As covered, not re-declaring things in the subclass is preferable. Since we’re talking about best practices, though, I’ll also suggest that if you’re not using dataclasses and your instance attributes are being set in your
__init__
, that’s where you should put your type annotations instead:This is briefer since you don’t need to declare each attribute in multiple places, and it gives you correct typechecking when you construct an instance:
If the parameters aren’t annotated, then you get the "correct" revealed type on the attributes, but it’s very easy for them to have the wrong actual types at runtime: