Моя функция выглядит как этот упрощенный пример кода:
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?
Решение проблемы
Проблема в том, что 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
. Это не полностью безопасно для типов, но, по крайней мере, вы все еще можете проверить свой dict.
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...
Если вы согласны с отказом от совместимости со старыми версиями Python, вы можете немного уменьшить свой псевдоним, используя новый синтаксис, представленный в Python 3.10:
# Python 3.10 lets you use 'dict' instead of Dict
ResultJson = dict[str, str | bool]
def my_func(condition: bool) -> ResultJson
result: ResultJson = {"success": False}
#...snip...
Вариант 3 является наиболее типобезопасным: вы можете назначать определенные типы различным полям в вашем словаре с помощью TypedDict:
from typing import Optional, TypedDict
# You can also use the older:
#
# ResultJson = TypedDict("ResultJson", {...})
#
#...syntax if you need to support versions of Python
# older then 3.6 or need to support keys that are not
# valid Python identifiers.
class ResultJson(TypedDict):
success: bool
message: Optional[str]
def my_func(condition: bool) -> ResultJson:
result: ResultJson = {"success": False, "message": None}
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
Главное предостережение в том, что typed_dict был добавлен в Python 3.8. Если вам нужна поддержка более старых версий Python, установите typing_extensions
пакет pip и используйте from typing_extensions import TypedDict
вместо него.
Комментариев нет:
Отправить комментарий