Строгая нотация типов в python
Задавал как то вопрос про нотации типов в функциях в python в стиле
def incr(number: int) -> int:
return number + 10
В таком случае, работая в IDE я буду получать соответствующие подсказки типов, по сути информируя среду о типах данных, с которыми работаю. И мне известно, что в отличии от условного с++, принимаемый на вход тип данных может не соответствовать тому что указан в нотации, IDE может и что-то скажет об этом, но сам интерпретатор никаким образом ругаться не станет. Вопрос вот в чём:
Существуют ли библиотеки с декораторами(?), автоматизирующую проверку типов, и вызывающие исключения, в случае несоответствии проверки?
Выражаясь псевдоязыком, в моей голове это должно выглядеть так:
def incr(number: int) -> int:
assert isinstance(number, int), TypeError
result = number + 10
assert isinstance(result, int), TypeError
return result
Только разумеется, я имею в виду автоматизацию процедуры проверки всех принимаемых и возвращаемых значений
Ответ:
Есть библиотека typeguard (вроде бы слышал про нее раньше, но сейчас нашел через этот ответ), которая умеет в том числе добавлять проверки типов получаемых и возвращаемых значений функций.
from typeguard import typechecked
@typechecked
def some_function(a: int, b: float, c: str, *args: str) -> bool:
...
return retval
@typechecked
class SomeClass:
# All type annotated methods (including static and class methods and properties)
# are type checked.
# Does not apply to inner classes!
def method(x: int) -> int:
...
Мой пример:
from typeguard import typechecked
@typechecked
def test(x: int) -> int:
return x
print(test(10)) # Выведет 10
print(test("abcd")) # TypeError: type of argument "x" must be int; got str instead
В том числе умеет проверять, например, что передан список целых чисел, а не произвольных значений:
from typing import List
from typeguard import typechecked
@typechecked
def test(x: List[int]) -> int:
return sum(x)
print(test([1, 2, 3, "A"])) # TypeError: type of argument "x"[3] must be int; got str instead
Похожая библиотека: strongtyping, работает похожим образом (правда, не умеет проверять тип возвращаемого значения):
from strongtyping.strong_typing import match_typing
@match_typing
def test(x: int) -> int:
return x
print(test("abcd"))
# Incorrect parameter: [x] `'abcd'`
# required: <class 'int'>
from strongtyping.strong_typing import match_typing
from typing import List
@match_typing
def test(x: List[int]) -> int:
return sum(x)
print(test([1, 2, 3, "A"]))
# Incorrect parameter: [x] `[1, 2, 3, 'A']`
# required: typing.List[int]