Ist es möglich, Python-Funktionsparameter, die als TypedDict-Schlüssel verwendet werden, mit Anmerkungen zu versehen, um
Posted: 29 Dec 2024, 12:01
Während ich an Code-Herausforderungen arbeite, versuche ich, Typanmerkungen für alle Funktionsparameter/Rückgabetypen zu verwenden. Ich verwende mypy im strikten Modus mit dem Ziel, keine Fehler zu machen.
Ich habe einige Zeit damit verbracht und komme nicht dahinter – Beispiel für ein Problem:
Gibt es eine Möglichkeit, dies zum Laufen zu bringen? Mir ist klar, dass ich # type:ignore an die Zeile anhängen kann, aber ich bin gespannt, ob es einen anderen Weg gibt.
Ich habe eine Reihe verschiedener Permutationen ausprobiert, beispielsweise das Sicherstellen von Feldern Entspricht einem der Literalwerte vor dem Diktatverständnis, aber nichts scheint zu helfen.
Mir gefällt die Lösung von @chepner. Leider konnte ich nicht herausfinden, wie ich es mit mypy im strikten Modus zum Laufen bringen kann – anhand seines Beispiels:
Ich bekomme:
Da das letzte get_movie_field nicht typannotiert ist.
Bei der Durchsicht der Mypy-Dokumente habe ich das letzte get_movie_field funktioniert wie folgt – aber es behebt das Problem immer noch nicht:
Das hat mich jedoch dazu inspiriert, einen anderen Ansatz zu finden. Ich sage nicht, dass es großartig ist, aber es funktioniert in dem Sinne, dass Mypy sich nicht beschwert:
Ich habe einige Zeit damit verbracht und komme nicht dahinter – Beispiel für ein Problem:
Code: Select all
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}
Code: Select all
# 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)
Ich habe eine Reihe verschiedener Permutationen ausprobiert, beispielsweise das Sicherstellen von Feldern Entspricht einem der Literalwerte vor dem Diktatverständnis, aber nichts scheint zu helfen.
Mir gefällt die Lösung von @chepner. Leider konnte ich nicht herausfinden, wie ich es mit mypy im strikten Modus zum Laufen bringen kann – anhand seines Beispiels:
Code: Select all
def get_movie_field(movies, field):
return {movie['Title']: {field: movie[field]} for movie in movies}
Code: Select all
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)
Bei der Durchsicht der Mypy-Dokumente habe ich das letzte get_movie_field funktioniert wie folgt – aber es behebt das Problem immer noch nicht:
Code: Select all
# @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}
Code: Select all
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)
Code: Select all
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}
Code: Select all
PS> mypy --strict program.py
Success: no issues found in 1 source file