Ist es möglich, Python-Funktionsparameter, die als TypedDict-Schlüssel verwendet werden, mit Anmerkungen zu versehen, umPython

Python-Programme
Anonymous
 Ist es möglich, Python-Funktionsparameter, die als TypedDict-Schlüssel verwendet werden, mit Anmerkungen zu versehen, um

Post by Anonymous »

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:
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)

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:
def get_movie_field(movies, field):
return {movie['Title']: {field: movie[field]} for movie in movies}

Ich bekomme:
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)

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:
# @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)

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:
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

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post