Ошибка Mypy - несовместимые типы в присваивании
Моя функция выглядит следующим образом:
def my_func() -> dict:
result = {"success": False}
if condition:
result["success"] = True
return result
else:
result["message"] = "error message"
return result
Когда я запускаю Mypy (версия 0.52), я получаю эту ошибку:
error: Incompatible types in assignment (expression has type "str", target has type "bool")
и ошибка указывает на вторую последнюю строку в моем примере кода. Почему mypy возвращает эту ошибку? мой код неверен (каким-либо образом) или это какая-то ошибка MyPy?
1 ответ
Проблема в том, что Mypy предположил, что тип вашего result
переменная Dict[str, bool]
из-за того, как вы сначала инициализировали его в строке 2.
Следовательно, когда вы пытаетесь вставить строку позже, mypy (по праву) жалуется. У вас есть несколько вариантов исправления кода, которые я перечислю в порядке убывания типа для большинства.
Вариант 1 - объявить ваш словарь так, чтобы его значения имели тип Any
- то есть ваши значения вообще не будут проверяться типом:
from typing import Any, Dict
def my_func(condition: bool) -> Dict[str, Any]:
result = {"success": False} # type: Dict[str, Any]
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
Обратите внимание, что нам нужно аннотировать вашу вторую строку, чтобы дать mypy подсказку о том, какой тип result
должно быть, чтобы помочь процессу вывода.
Если вы используете Python 3.6+, вы можете аннотировать эту строку, используя следующий альтернативный синтаксис, который использует переменные аннотации (которые являются новыми с Python 3.6):
result: Dict[str, Any] = {"success": False}
Вариант 2 немного более безопасен для типов - объявите ваши значения как strs или bools, но не более того, используя Union
, Это не совсем безопасно, но, по крайней мере, у вас все еще могут быть некоторые проверки вашего диктата.
from typing import Any, Dict
def my_func(condition: bool) -> Dict[str, Union[str, bool]]:
result = {"success": False} # type: Dict[str, Union[str, bool]]
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
Возможно, вы обнаружите, что эта аннотация типа немного длинная / раздражающая для типа, поэтому вы можете использовать псевдонимы типов для удобства чтения (и, возможно, использовать синтаксис переменной аннотации), например, так:
ResultJson = Dict[str, Union[str, bool]]
def my_func(condition: bool) -> ResultJson
result: ResultJson = {"success": False}
# ...snip...
Вариант 3 является наиболее безопасным для типов, хотя он требует использования экспериментального типа "TypedDict", который позволяет назначать определенные типы различным полям в вашем dict. Тем не менее, используйте этот тип на свой страх и риск - AFAIK он еще не был добавлен в PEP 484, что означает, что другие инструменты проверки типа (такие как средство проверки Пихарма) не обязаны это понимать. Сама Mypy только недавно добавила поддержку TypedDict, и поэтому все еще может содержать ошибки:
from typing import Optional
from mypy_extensions import TypedDict
ResultJson = TypedDict('ReturnJson', {'success': bool, 'message': Optional[str]})
def my_func(condition: bool) -> ResultJson:
result = {"success": False, "message": None} # type: ResultJson
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
Обязательно установите mypy_extensions
пакет, если вы хотите использовать эту опцию.