Основы mypy#

Так как сам Python никак не проверяет указанные типы данных, надо использовать какой-то дополнительный модуль для проверки. Один из таких модулей - mypy.

Mypy выполняет статический анализ кода - проверяет соответствие типов данных без выполнения кода.

Примечание

Mypy не единственный проект такого типа. Другие модули: pyre, pytype.

Пример запуска скрипта с помощью mypy:

$ mypy example_01_function_check_ip.py
example_01_function_check_ip.py:13: error: Argument 1 to "check_ip" has incompatible type "int"; expected "str"
Found 1 error in 1 file (checked 1 source file)

Писать аннотацию для переменных нужно далеко не всегда. Как правило, того типа который «угадал» mypy достаточно. Например, в этом случае mypy понимает, что ip это строка:

ip = '10.1.1.1'

И не будет выводить никаких ошибок:

$ mypy example_03_variable.py

Success: no issues found in 1 source file

Однако, если переменная может быть и строкой и числом:

ip = '10.1.1.1'
ip = 3

mypy посчитает это ошибкой:

example_03_variable.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "str")
Found 1 error in 1 file (checked 1 source file)

В таком случае надо явно указать, что переменная может быть числом или строкой:

from typing import Union

ip: Union[int, str] = '10.1.1.1'
ip = 3

strict#

def func1(a: str, b: str) -> str:
    return a + b

def func2(c, d):
    result = func1(4, 6)
    return c + d

По умолчанию, mypy игнорирует функции без аннотации типов:

$ mypy testme.py
Success: no issues found in 1 source file

С параметром strict mypy проверяет эти функции и их работу с другими объектами:

$ mypy testme.py --strict
testme.py:4: error: Function is missing a type annotation
testme.py:5: error: Argument 1 to "func1" has incompatible type "int"; expected "str"
testme.py:5: error: Argument 2 to "func1" has incompatible type "int"; expected "str"
Found 3 errors in 1 file (checked 1 source file)

reveal#

reveal_type

reveal_locals:

def check_passwd(username: str, password: str,
                 min_length: int = 8, check_username: bool = True) -> bool:
    reveal_locals()
    if len(password) < min_length:
        print('Пароль слишком короткий')
        return False
    elif check_username and username in password:
        print('Пароль содержит имя пользователя')
        return False
    else:
        print(f'Пароль для пользователя {username} прошел все проверки')
        return True
example_02_function_check_passwd.py:4: note: Revealed local types are:
example_02_function_check_passwd.py:4: note:     check_username: builtins.bool
example_02_function_check_passwd.py:4: note:     min_length: builtins.int
example_02_function_check_passwd.py:4: note:     password: builtins.str
example_02_function_check_passwd.py:4: note:     username: builtins.str