es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , , , ,

Answer

  1. Avatar for 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 de record. 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:

    from typing import TypeVar
    
    T = TypeVar('T')
    
    class Abstracto(ABC):
        record: T
    
    class SubA(Abstracto):
        record: DjangoModeloA
    
    class SubB(Abstracto):
        record: DjangoModeloB
    

    Con este código, mypy ya no se quejará, porque record en Abstracto 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 utilizando TypeVar('T'), que crea una nueva variable de tipo llamada T. 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 a TypeVar 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.

Comments are closed.