Cómo declarar variables de instancia en ABC cuyas implementaciones podrían tener tipos distintos.
Tengo una clase abstracta llamada ABC
que tendrá una variable de instancia, digamos record
, en todas sus clases de implementación. Para mejorar la legibilidad, quiero que los lectores sepan que las instancias de esa ABC
deben tener una variable de instancia llamada record
.
Sin embargo, el tipo de record
varía en diferentes clases de implementación. Y quiero evitar que mi ABC
especifique todos los posibles tipos que record
podría tener (por ejemplo, record: DjangoModelA | DjangoModelB
en ABC) porque esto no me suena correcto.
Aquí hay una versión simplificada de mi código actual:
class Abstract(ABC):
record: None
class SubA(Abstract):
record: DjangoModelA
class SubB(Abstract):
record: DjangoModelB
por lo cual mypy muestra el siguiente error:
error: Tipos incompatibles en la asignación (la expresión tiene el tipo "DjangoModelA", la clase base "Abstract" definió el tipo como "None")
error: Tipos incompatibles en la asignación (la expresión tiene el tipo "DjangoModelB", la clase base "Abstract" definió el tipo como "None")
¿Cómo debo declarar la clase base abstracta para que mypy y yo estemos satisfechos con ella?
davy.ai
Para declarar una variable de instancia en una clase base abstracta permitiendo diferentes tipos en sus clases de implementación, puedes utilizar
typing.TypeVar
para crear un tipo de marcador de posición que represente el tipo derecord
. Luego puedes utilizar este tipo de marcador de posición como anotación de tipo para la variable de instancia en la clase base, y en las clases de implementación puedes sustituir el marcador de posición por el tipo real.Aquí hay un ejemplo basado en tu código:
Con este código, mypy ya no se quejará, porque
record
enAbstracto
ahora tiene un tipo de marcador de posición que puede ser reemplazado por tipos reales en las clases de implementación.Ten en cuenta que el tipo de marcador de posición
T
se define utilizandoTypeVar('T')
, que crea una nueva variable de tipo llamadaT
. Puedes usar un nombre diferente si lo prefieres, pero convencionalmente los nombres de las variables de tipo son una letra mayúscula. El argumento'T'
pasado aTypeVar
es opcional y puede ser cualquier cadena que identifique la variable de tipo, pero usar el mismo nombre que la variable en sí misma puede mejorar la legibilidad.