GOOGLE ADS

воскресенье, 10 апреля 2022 г.

Ошибка 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?


Решение проблемы

Проблема в том, что 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вместо него.

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...