Работая над проблемами кода, я пытаюсь использовать аннотации типов для всех параметров функций/типов возвращаемых данных. Я использую mypy в строгом режиме, чтобы избежать ошибок.
Я потратил на это некоторое время и не могу понять – пример проблемы:
from typing import Literal, NotRequired, TypedDict
class Movie(TypedDict):
Title: str
Runtime: str
Awards: str
class MovieData(TypedDict):
Awards: NotRequired[str]
Runtime: NotRequired[str]
def get_movie_field(movies: list[Movie], field: Literal['Awards', 'Runtime']) -> dict[str, MovieData]:
return {movie['Title']: {field: movie[field]} for movie in movies}
# Check with mypy 1.14.0:
PS> mypy --strict .\program.py
program.py:13: error: Expected TypedDict key to be string literal [misc]
Found 1 error in 1 file (checked 1 source file)
Есть ли какой-нибудь способ заставить это работать? Я понимаю, что могу добавить # type: ignore к строке, но мне интересно, есть ли другой способ.
Я пробовал кучу разных перестановок, таких как обеспечение поля соответствует одному из литеральных значений перед пониманием dict, но, похоже, ничего не помогает.
Мне нравится решение @chepner. К сожалению, я не смог понять, как заставить его работать с mypy в строгом режиме - на его примере:
def get_movie_field(movies, field):
return {movie['Title']: {field: movie[field]} for movie in movies}
Я получаю:
PS> mypy --strict program.py
program.py:18: error: Function is missing a type annotation [no-untyped-def]
Found 1 error in 1 file (checked 1 source file)
Поскольку последнее get_movie_field не имеет аннотации типа.
Просматривая документы mypy, я обновил последнее get_movie_field функционируют следующим образом, но это все равно не решает проблему:
# @chepner's full solution updated with type annotations for
# last get_movie_field:
from typing import Literal, NotRequired, TypedDict, overload
class Movie(TypedDict):
Title: str
Runtime: str
Awards: str
class MovieData(TypedDict):
Awards: NotRequired[str]
Runtime: NotRequired[str]
@overload
def get_movie_field(movies: list[Movie], field: Literal['Awards']) -> dict[str, MovieData]:
...
@overload
def get_movie_field(movies: list[Movie], field: Literal['Runtime']) -> dict[str, MovieData]:
...
def get_movie_field(movies: list[Movie], field: Literal['Awards']|Literal['Runtime']
) -> dict[str, MovieData]:
return {movie['Title']: {field: movie[field]} for movie in movies}
PS> mypy --strict program.py
program.py:19: error: Expected TypedDict key to be string literal [misc]
Found 1 error in 1 file (checked 1 source file)
Однако это вдохновило меня на поиск другого подхода. Я не говорю, что это здорово, но это работает в том смысле, что mypy не жалуется:
from typing import Literal, NotRequired, TypedDict
class Movie(TypedDict):
Title: str
Runtime: str
Awards: str
class MovieData(TypedDict):
Awards: NotRequired[str]
Runtime: NotRequired[str]
def create_MovieData(key: str, value: str) -> MovieData:
"""Creates a new TypedDict using a given key and value."""
if key == 'Awards':
return {'Awards': value}
elif key == 'Runtime':
return {'Runtime': value}
raise ValueError(f"Invalid key: {key}")
def get_movie_field(movies: list[Movie], field: Literal['Awards', 'Runtime']) -> dict[str, MovieData]:
return {movie['Title']: create_MovieData(field, movie[field]) for movie in movies}
PS> mypy --strict program.py
Success: no issues found in 1 source file
Подробнее здесь: https://stackoverflow.com/questions/793 ... eddict-key
Можно ли ввести параметр функции annotate Python, используемый в качестве ключа TypedDict, чтобы сделать mypy счастливым ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение