1
votes

Comment obtenir des indices de type pour les attributs d'un objet?

Je veux obtenir les indices de type pour les attributs d'un objet. Je ne peux obtenir que les indices pour la classe et non une instance de celle-ci.

J'ai essayé d'utiliser foo_instance.__class__ partir d' ici mais cela ne montre que les variables de classe.

Donc, dans l'exemple, comment obtenir le type de bar ?

class foo:
    var: int = 42
    def __init__(self):
        self.bar: int = 2

print(get_type_hints(foo)) # returns {'var': <class 'int'>}


0 commentaires

4 Réponses :


1
votes

Les indices n'existent qu'au niveau de la classe - au moment où une instance est créée, le type de ses attributs sera celui de la valeur qui leur a été attribuée. Vous pouvez obtenir le type de n'importe quel attribut d'instance en utilisant la première forme de la fonction intégrée type() - par exemple, type(foo_instance.var) .


9 commentaires

la fonction type renvoie le type, pas l'indication de type. cela doit être possible d'une certaine manière car pycharm montre l'indication de type (pas le type) de l'attribut en cas d'accès


Il doit utiliser la __class__ l'objet avec le nom de l'attribut pour l'afficher.


Les indices de type sont stockés dans l'attribut __annotations__ une classe comme décrit dans la réponse @Remco Haszing à la question liée - car c'est un dictionnaire. vous pouvez rechercher le nom de l'attribut dans cela.


class ne fonctionnera qu'avec la variable class et si cela fonctionnait avec type (), il affichera uniquement le type du contenu de la variable et non l'indication de type, pycharm affiche correctement l'indication de type si un type différent est assigné au attribut


le __annotations__ ne stocke que les variables de classe et ne stocke pas les indices de type d'attribut, c'est le même que get_type_hints et ne contient pas de bar


Les annotations sont stockées au niveau du module ou de niveau de classe, donc peut être trouvée dans le __annotations__ attribut d'un objet __class__ , mais les annotations au niveau de la fonction ne sont pas évaluées et ne sont pas stockées (voir la dernière phrase des effets d' exécution de type annotations ). Je pense que cela signifie que les informations que vous souhaitez ne sont tout simplement disponibles nulle part, sauf dans le code source.


merci, cela répond à ma question @martineau, j'en ai fait un message avec des informations sur la façon d'obtenir ces informations avec un avertissement que c'est probablement une mauvaise idée


S'il répond à votre question, veuillez envisager de l'accepter. Voir Comment l'acceptation d'une réponse fonctionne-t-elle?


je le ferai dans 20 heures quand ça me permettra



0
votes

Cette information n'est pas évaluée et n'existe que dans le code source. si vous devez obtenir ces informations, vous pouvez utiliser le module ast et extraire vous-même les informations du code source, si vous avez accès au code source.

Vous devez également vous demander si vous avez besoin de ces informations car dans la plupart des cas, la réévaluation du code source demandera beaucoup d'efforts.


0 commentaires

0
votes

C'est peut-être un hack, et vous devez être le créateur de vos instances, mais il existe un sous-ensemble de cas dans lesquels l'utilisation d'une classe de données vous donnera ce que vous voulez;

Python 3.7+

@dataclass
class Foo:
    bar: str = 2

if __name__ == '__main__':
    f = Foo()
    print(f.bar)
    print(get_type_hints(f))

2
{'bar': <class 'str'>}


0 commentaires

0
votes

J'ai juste eu le même problème. La documentation python n'est pas si claire puisque l'exemple est fait avec ce qui est maintenant officiellement appelé dataclass.

class foo:
    var: int = 42
    def __init__(self, bar: int = 2):
        self.bar = int

print(get_type_hints(foo.__init__))

Cela donne l'impression que get_type_hints() fonctionne directement sur la classe. Il s'avère que get_type_hints() renvoie des indices basés sur les fonctions, pas sur la classe. De cette façon, il peut être utilisé avec les deux si nous le savons. Une classe normale n'est évidemment pas instanciée lors de sa déclaration, elle n'a aucune des variables définies dans la __init__() qui n'a pas encore été appelée. Il ne pourrait pas en être ainsi non plus si nous voulons avoir la possibilité d'obtenir les indices de type à partir de variables à l'échelle de la classe.

Donc, vous pouvez soit l'appeler sur __init__() , c'est-à-dire si des variables sont passées en arguments (oui, j'ai vu que ce n'est pas dans votre exemple, mais cela pourrait aider les autres car je n'ai vu cela nulle part pendant des heures de recherche);

Student(NamedTuple):
    name: Annotated[str, 'some marker']

get_type_hints(Student) == {'name': str}
get_type_hints(Student, include_extras=False) == {'name': str}
get_type_hints(Student, include_extras=True) == {
    'name': Annotated[str, 'some marker']
}

Enfin, pour votre exemple exact, je crois que vous avez deux choix. Vous pouvez instancier un objet temporaire et utiliser del pour le nettoyer juste après si votre logique le permet. Ou déclarez vos variables comme des variables de classe avec ou sans valeurs par défaut pour pouvoir les obtenir avec get_type_hints() et les affecter plus tard dans les instanciations.


0 commentaires