¿Cómo puedo obtener nuevos tipos de campo de clase de datos de Python 3.7?

4 minutos de lectura

Avatar de usuario de Kamyar
Kamyar

Python 3.7 presenta una nueva característica llamada clases de datos.

from dataclasses import dataclass

@dataclass
class MyClass:
    id: int = 0
    name: str=""

Al usar sugerencias de tipo (anotación) en los parámetros de función, puede obtener fácilmente tipos anotados usando el módulo de inspección. ¿Cómo puedo obtener tipos de campo de clase de datos?

  • Preferiría no usar campos privados como ese. Gracias de cualquier manera

    – Kamyar

    21 de agosto de 2018 a las 10:57

  • No es un campo privado. También acaba de aceptar una respuesta que usa atributos “dunder”.

    – jonrsharpe

    21 de agosto de 2018 a las 10:58

  • Por cierto, se recomienda la opción get_type_hints que el uso de __annotations__

    –Andriy Ivaneyko

    21 de agosto de 2018 a las 16:46

avatar de usuario de user2357112
usuario2357112

inspeccionando __annotations__ le da las anotaciones sin procesar, pero esas no corresponden necesariamente a los tipos de campo de una clase de datos. Cosas como ClassVar e InitVar aparecen en __annotations__aunque no sean campos y los campos heredados no se muestren.

En su lugar, llama dataclasses.fields en la clase de datos e inspeccionar los objetos de campo:

field_types = {field.name: field.type for field in fields(MyClass)}

Ni __annotations__ ni fields resolverá las anotaciones de cadenas. Si desea resolver las anotaciones de cadenas, la mejor manera es probablemente typing.get_type_hints. get_type_hints incluirá ClassVars e InitVars, por lo que usamos fields para filtrarlos:

resolved_hints = typing.get_type_hints(MyClass)
field_names = [field.name for field in fields(MyClass)]
resolved_field_types = {name: resolved_hints[name] for name in field_names}

  • Para agregar a esto, las clases de datos admiten la herencia pero __annotations__ no resolvería los campos de la clase principal

    – olik1

    24 de julio de 2021 a las 2:22

  • ¿Qué hay de obtener también los valores predeterminados de cada campo?

    –Eduardo Pignatelli

    23 de diciembre de 2022 a las 12:38


  • @EduardoPignatelli: field.default (Cuál podría ser dataclasses.MISSING si no hay ningún valor por defecto).

    – usuario2357112

    23 de diciembre de 2022 a las 12:48

Avatar de usuario de Serbitar
Serbitar

from dataclasses import dataclass

@dataclass
class MyClass:
    id: int = 0
    name: str="" 

myclass = MyClass()

myclass.__annotations__
>> {'id': int, 'name': str}
myclass.__dataclass_fields__
>> {'id': Field(name="id",type=<class 'int'>,default=0,default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD),
 'name': Field(name="name",type=<class 'str'>,default="",default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)}

en una nota al margen también hay:

myclass.__dataclass_params__
>>_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)

  • El autor puso el trabajo en el formato de una respuesta correcta a la pregunta. ¿Puede señalar alguna documentación que no se recomienda escribir respuestas que se superponen con los comentarios?

    – Robx

    21 de agosto de 2018 a las 10:41

  • Preferiría no usar campos privados como ese. Necesito algo como inspeccionar el objeto de firma del módulo.

    – Kamyar

    21 de agosto de 2018 a las 10:58

  • Preste atención aquí, si no está en 3.10 y usa from __future__ import annotations el type el campo será el str representación del tipo, no del type sí mismo.

    – Wolfgang Pfnür

    28 de octubre de 2021 a las 12:07

  • @WolfgangPfnür Gracias por este comentario, me ha mordido esto en este momento, preguntándome por qué todas las respuestas eran “incorrectas”.

    – Quimby

    3 de enero de 2022 a las 14:28


  • @WolfgangPfnür Lo mismo aquí, comentario salvavidas. Esta es una ‘característica’ extremadamente desagradable.

    – Julien Débache

    18 de febrero de 2022 a las 13:24

Avatar de usuario de Andriy Ivaneyko
andriy ivaneyko

El dataclasses.py es el módulo que proporciona decorador y funciones para generar métodos de clase regulares mediante el uso de las anotaciones de campo. Lo que significa que después de la clase de procesamiento, los campos definidos por el usuario se formarán utilizando PEP 526 Sintaxis de anotaciones de variables. Se puede acceder a las anotaciones del módulo como __annotations__.

De acuerdo con la Efectos de tiempo de ejecución de las anotaciones de tipo se puede acceder a los tipos anotados a través de __annotations__ atributo o por el uso del escribiendo.get_type_hintseste último el recomendado.

Por favor, vea algunos ejemplos de código a continuación:

from typing import Dict, ClassVar, get_type_hints
from dataclasses import dataclass

@dataclass
class Starship:
    hitpoints: int = 50


get_type_hints(Starship) // {'hitpoints': int}
Starship.__annotations__ // {'hitpoints': int}
dataclasses.__annotations__ // The annotations of the dataclasses module.
get_type_hints(get_type_hints)

¿Ha sido útil esta solución?