Строгая нотация типов в 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
Только разумеется, я имею в виду автоматизацию процедуры проверки всех принимаемых и возвращаемых значений
Ответы (2 шт):
Python - динамически типизированый язык, максимум можно сделать типа такого костыля:
from typing import get_type_hints
def static(func):
def wrapper(*args):
typehints = list(get_type_hints(func).values())
with_return = False
if len(args) > len(typehints):
raise SyntaxError('invalid syntax.')
elif len(args) < len(typehints):
typehints = typehints[:-1]
with_return = True
else:
pass
for i in args:
for j in typehints:
if not isinstance(i, j):
raise TypeError(f'{j} type is not {i} type')
if with_return:
return func(*args)
else:
func(*args)
return wrapper
Но данный декоратор обязывает человека использовать тайпхинты, плюс у него есть ещё пара минусов.
Есть библиотека 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]