Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

232
Vistas
Heredar tipo genérico en python 3 con tipeo

Estoy haciendo algunos experimentos escribiendo en Python 3.6 y mypy. Quiero diseñar una clase de entidad que se pueda instanciar de dos maneras:

  • Mediante el uso de un inicializador ordinario ( p = Person(name='Hannes', age=27) )
  • Estáticamente desde un objeto de estado ( p = Person.from_state(person_state) ).

La clase Entity , de la que deriva Person , tiene como parámetro genérico la clase estado. Sin embargo, al validar el código con mypy, recibo un error de que Person.from_state no selecciona el tipo de estado de la clase de la que hereda:

untitled2.py:47: error: el argumento 1 a "from_state" de "Entity" tiene un tipo incompatible "UserState"; "Tipo de estado" esperado

Pensé que al heredar de Entity[UserState] , StateType estaría vinculado a UserState y las firmas de métodos en las clases secundarias se actualizarían en consecuencia.

Este es el código completo. He marcado la línea donde sospecho que estoy haciendo las cosas mal con ????? . La línea 47 está casi al final y está marcada en el código.

 from typing import TypeVar, Generic, NamedTuple, List, NewType EntityId = NewType('EntityId', str) StateType = TypeVar('StateType') class Entity(Generic[StateType]): id: EntityId = None state: StateType = None @classmethod def from_state(cls, state: StateType): # ????? ret = object.__new__(cls) ret.id = None ret.state = state return ret def assign_id(self, id: EntityId) -> None: self.id = id class UserState(NamedTuple): name: str age: int class User(Entity[UserState]): def __init__(self, name, age) -> None: super().__init__() self.state = UserState(name=name, age=age) @property def name(self) -> str: return self.state.name @property def age(self) -> int: return self.state.age def have_birthday(self) -> None: new_age = self.state.age+1 self.state = self.state._replace(age=new_age) # Create first object with constructor u1 = User(name='Anders', age=47) # Create second object from state user_state = UserState(name='Hannes', age=27) u2 = User.from_state(user_state) # Line 47 print(u1.state) print(u2.state)
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Este fue un error en mypy que se corrigió en mypy 0.700. Como señalaron varias personas en los comentarios, esa línea de código se valida bien en las versiones más nuevas.

Tenga en cuenta que en las versiones más recientes de mypy, el código de la pregunta tiene un problema diferente:

 main.py:8: error: Incompatible types in assignment (expression has type "None", variable has type "EntityId") main.py:9: error: Incompatible types in assignment (expression has type "None", variable has type "StateType")

Pero eso está fuera del alcance de la pregunta y depende de usted para resolverlo como desee.

over 4 years ago · Santiago Trujillo Denunciar

0

Sé que esta pregunta es un poco antigua, pero solo para futuras referencias:

 from __future__ import annotations from typing import NamedTuple, Optional, Type class UserState(NamedTuple): name: str age: int class Entity: id: Optional[str] state: UserState @classmethod def from_state(cls: Type[Entity], state: UserState) -> Entity: entity_from_state: Entity = object.__new__(cls) entity_from_state.id = None entity_from_state.state = state return entity_from_state def assign_id(self, id: str) -> None: self.id = id class User(Entity): def __init__(self, name: str, age: int) -> None: self.state = UserState(name=name, age=age) @property def name(self) -> str: return self.state.name @property def age(self) -> int: return self.state.age def have_birthday(self) -> None: new_age = self.state.age + 1 self.state = self.state._replace(age=new_age) # Create first object with constructor u1 = User(name="Anders", age=47) # Create second object from state user_state = UserState(name="Hannes", age=27) u2 = User.from_state(user_state) # Line 47 print(u1.state) print(u2.state)
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda