Аннотации типов в Python
Все мы знаем, что Python - язык с динамической типизацией. Но с довольно давних пор в нем также появилась возможность явно указывать типы данных и это здорово матчится с принципом дзена Python: явное лучше неявного (Explicit is better than implicit).
Да, аннотации являются необязательными, но я бы сказал, что это правила хорошего тона для программистов. Важно четко понимать, с чем ты работаешь. Это поможет избежать ошибок (зачастую нетривиальных), когда параметр обрабатывает несколько типов данных или принимает какие-то сложные объекты. Если вы работаете в большой команде, это просто облегчит вам жизнь.
Когда мы прописываем тип данных для какого-то объекта или параметра - просто через двоеточие, для возвращаемых типов - указываем через стрелочку.
Встроенные типы и модуль typing
name: str = "Dude" age: int = 49 height: float = 185.1
Для итерируемых объектов мы можем явно указать тип Iterable
, когда нам не принципиально, что именно это будет - список, кортеж и т.д.
from typing import Iterable def my_func(param: Iterable[int]) -> None: for num in param: print(num) my_func(param=(1, 2, 3)) my_func(param={1, 2, 3}) my_func(param=[1, 2, 3])
Когда нам нужно использовать несколько типов, мы можем использовать тип Union
из модуля typing
, или просто символ |
между типами (второе предпочтительнее).
from typing import Union param_1: Union[str, int] param_2: str | int
Для опциональных значений существует отдельный тип Optional
или просто | None
. Здесь также предпочтительно второе.
from typing import Optional param_1: Optional[str] param_2: str | None
Отдельно упомяну про тип Any
из модуля typing
. По сути он и означает то, чем является - любой тип данных. Например, если вы работаете с большим словарем с кучей вложенностей разных типов, можно просто прописать param: dict[str, Any]
. Нет боли от прописывания всех типов + понятно, что работаешь с словарем. Конечно, без необходимости лучше избегать этот тип и явно прописывать то, с чем работаешь.
Здесь никакой магии, как и писал выше - просто указываем type hints через стрелочку:
def my_func(param1: int, param2: int) -> int: return param1 + param2 def __init__(self, param: str) -> None: self.param: str = param
Стоит упомянуть, что если в type hints прописан один тип данных и при этом вы работаете с другим - ошибок не будет, но IDE подсветит такие моменты.
Можно ли автоматически проверять типизацию?
Да. Для этого понадобится кое-что прикрутить к проекту. Чаще всего предпочтение отдается mypy или ruff. Так линтеры / чекеры будут стоять на страже качества кода и не придется уделять этому дополнительное внимание на код ревью.
Не бойтесь указывать аннотации типов где только возможно и мир станет чуточку лучше. :)