Можно ли ввести параметр функции annotate Python, используемый в качестве ключа TypedDict, чтобы сделать mypy счастливымPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Можно ли ввести параметр функции annotate Python, используемый в качестве ключа TypedDict, чтобы сделать mypy счастливым

Сообщение Anonymous »

Работая над проблемами кода, я пытаюсь использовать аннотации типов для всех параметров функций/типов возвращаемых данных. Я использую 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»