web-dev-qa-db-fra.com

Comment obtenir de nouveaux types de champs de classe de données Python 3.7?

Python 3.7 introduit une nouvelle fonctionnalité appelée classes de données.

from dataclasses import dataclass

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

Lors de l'utilisation d'indications de type (annotation) dans les paramètres de fonction, vous pouvez facilement obtenir des types annotés à l'aide du module inspect. Comment puis-je obtenir des types de champs de classe de données?

8
Kamyar
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)}

sur une note de côté il y a aussi:

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

L'inspection __annotations__ vous donne les annotations brutes, mais celles-ci ne correspondent pas nécessairement aux types de champs d'une classe de données. Des éléments tels que ClassVar et InitVar apparaissent dans __annotations__, même s'ils ne sont pas des champs, et les champs hérités n'apparaissent pas.

À la place, appelez dataclasses.fields sur la classe de données et inspectez les objets de champ:

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

Ni __annotations__ ni fields ne résoudront les annotations de chaînes. Si vous souhaitez résoudre les annotations de chaîne, le meilleur moyen est probablement typing.get_type_hints . get_type_hints inclut ClassVars et InitVars, nous utilisons donc fields pour les filtrer:

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}
6
user2357112

Le dataclasses.py _ est le module qui fournit le décorateur et les fonctions permettant de générer des méthodes de classe régulières à l'aide des annotations de champ. Cela signifie qu'après la classe de traitement, les champs définis par l'utilisateur doivent être formés à l'aide de syntaxe PEP 526 des annotations variables . Le module annotations est accessible en tant que __annotations__.

Selon les effets d'exécution des annotations de type , les types annotés sont accessibles via l'attribut __annotations__ ou par l'utilisation de typing.get_type_hints , le dernier recommandé.

Veuillez voir quelques exemples de code ci-dessous:

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)
1
Andriy Ivaneyko