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?
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 serdataclasses.MISSING
si no hay ningún valor por defecto).– usuario2357112
23 de diciembre de 2022 a las 12:48
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
eltype
el campo será elstr
representación del tipo, no deltype
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
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)
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