Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

129
Visualizações
Anotar variable de clase de clase de datos con valor de tipo

Tenemos varias clases de datos que representan varios resultados con un ancestro común Result . Luego, cada resultado proporciona sus datos utilizando su propia subclase de ResultData . Pero tenemos problemas para anotar el caso correctamente.

Se nos ocurrió la siguiente solución:

 from dataclasses import dataclass from typing import ClassVar, Generic, Optional, Sequence, Type, TypeVar class ResultData: ... T = TypeVar('T', bound=ResultData) @dataclass class Result(Generic[T]): _data_cls: ClassVar[Type[T]] data: Sequence[T] @classmethod def parse(cls, ...) -> T: self = cls() self.data = [self._data_cls.parse(...)] return self class FooResultData(ResultData): ... class FooResult(Result): _data_cls = FooResultData

pero dejó de funcionar últimamente con el error ClassVar cannot contain type variables [misc] . También va en contra de PEP 526, consulte https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations , que nos perdimos anteriormente.

¿Hay alguna manera de anotar este caso correctamente?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Como se insinuó en los comentarios, el atributo _data_cls podría eliminarse, suponiendo que se use para fines de sugerencia de tipo. La forma correcta de anotar una clase genérica definida como class MyClass[Generic[T]) es usar MyClass[MyType] en las anotaciones de tipo.

Por ejemplo, es de esperar que lo siguiente funcione en mypy. Solo probé en Pycharm y parece inferir el tipo lo suficientemente bien al menos.

 from dataclasses import dataclass from functools import cached_property from typing import Generic, Sequence, TypeVar, Any, Type T = TypeVar('T', bound='ResultData') class ResultData: ... @dataclass class Result(Generic[T]): data: Sequence[T] @cached_property def data_cls(self) -> Type[T]: """Get generic type arg to Generic[T] using `__orig_class__` attribute""" # noinspection PyUnresolvedReferences return self.__orig_class__.__args__[0] def parse(self): print(self.data_cls) @dataclass class FooResultData(ResultData): # can be removed this_is_a_test: Any = 'testing' class AnotherResultData(ResultData): ... # indicates `data` is a list of `FooResultData` objects FooResult = Result[FooResultData] # indicates `data` is a list of `AnotherResultData` objects AnotherResult = Result[AnotherResultData] f: FooResult = FooResult([FooResultData()]) f.parse() _ = f.data[0].this_is_a_test # no warnings f: AnotherResult = AnotherResult([AnotherResultData()]) f.parse()

Producción:

 <class '__main__.FooResultData'> <class '__main__.AnotherResultData'>

Y, por supuesto, aquí hay una prueba de que parece estar funcionando de mi parte:

ingrese la descripción de la imagen aquí

over 4 years ago · Santiago Trujillo Relatório

0

Al final, simplemente reemplacé la variable en la anotación _data_cls con la clase base y arreglé la anotación de subclases como lo señaló @ rv.kvetch en su respuesta .

La desventaja es la necesidad de definir la clase de resultado dos veces en cada subclase, pero en mi opinión es más legible que extraer la clase en propiedad.

La solución completa:

 from dataclasses import dataclass from typing import ClassVar, Generic, Optional, Sequence, Type, TypeVar class ResultData: ... T = TypeVar('T', bound=ResultData) @dataclass class Result(Generic[T]): _data_cls: ClassVar[Type[ResultData]] # Fixed annotation here data: Sequence[T] @classmethod def parse(cls, ...) -> T: self = cls() self.data = [self._data_cls.parse(...)] return self class FooResultData(ResultData): ... class FooResult(Result[FooResultData]): # Fixed annotation here _data_cls = FooResultData
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda