Cómo escribir correctamente los métodos de Python que devuelven un diccionario con una instancia de tipo genérico y su propiedad de tipo genérico.
Tengo la siguiente función Python y quiero escribirla de tal forma que mypy entienda el tipo de retorno como un diccionario, con el tipo de valor como el tipo de ítem y el tipo de identificación como el tipo de clave:
def id_map(items):
return {item.id: item for item in items}
El enfoque actual se ve así:
from typing import Iterable, Protocol, TypeVar
S = TypeVar("S", covariant=True, bound="ClassWithId")
T = TypeVar("T", covariant=True)
class ClassWithId(Protocol[S, T]):
def new(cls: type[S], args: Any, **kwargs: Any) -> "ClassWithId[S, T]":
...
@property
def id(self: S) -> T:
...
def id_map(items: Iterable[ClassWithId[S, T]]) -> dict[T, S]:
return {item.id: cast(S, item) for item in items}
Esto resulta actualmente en el tipo builtins.dict[Any, Any]
. No puedo pensar en una implementación diferente que haga que esto funcione. Me pregunto si esto es posible utilizando mypy.
davy.ai
Sí, es posible escribir la función
id_map
de tal manera que mypy comprenda que el tipo de retorno es un diccionario cuyos valores corresponden al tipo de los elementos y las claves corresponden al tipo del id.Aquí hay un ejemplo de cómo hacerlo:
En este ejemplo, definimos dos variables de tipo,
T
yS
, dondeT
representa el tipo de la clave yS
representa el tipo de los elementos en la entrada iterableitems
. Luego definimos una claseClassWithId
con un atributoid_
de tipoT
, y finalmente, definimos la funciónid_map
con el tipo de retorno deseado deDict[T, S]
.Con esta implementación, mypy puede inferir correctamente el tipo de retorno
Dict[T, S]
para la funciónid_map
.