Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Ces trois manières de lier un attribut sont-elles réellement équivalentes ?

11 réponses
Avatar
Francois
Bonjour à tous,

Je me permets de poster ce message car je me perds un peu dans les
différentes manières de lier un attribut d'un objet instance.
Pouvez-vous me dire quelles sont les éventuelles différences entre 1/,
2/ et 3/ ?

1/ obj.x = <valeur>

2/ obj.__dict__['x'] = <valeur>

3/ obj.__setattr__('x', <valeur>)

où <valeur> est une expression quelconque et où l'on suppose que obj est
l'identifiant d'un objet (nouveau style), instance d'une classe C.

Je n'ai pas la réponse bien sûr, même si j'ai l'impression qu'il n'y a
aucune différence entre ces trois moyens. J'ai l'impression (sans
certitude évidemment) que 1/ est *toujours* traduit en interne par 3/
par le compilateur bytecode et que 3/ est par défaut défini comme
strictement équivalent à 2/ sauf si on a pris le soin de redéfinir la
méthode spéciale __setattr__ dans le corps de la classe C . Est-ce
correct ? Pouvez vous m'aider à tirer cela au clair ? Je suis un peu
surpris qu'on puisse faire une même chose de trois manières différentes.

Merci d'avance.


--
François

1 réponse

1 2
Avatar
Bruno Desthuilliers
Francois a écrit :

J'ai essayé de me documenter un peu, et il me semble que c'est vraiment
les descripteurs qui complexifient les choses. J'avoue avoir du mal à
comprendre l'intérêt des descripteurs, je pense que ça doit être réservé
à de la programmation un peu exotique.



Erreur. Le protocole descripteur est une des fonctionnalités clés du
modèle objet de Python. C'est lui qui permets les attributs calculés -
donc (entre autres...) les méthodes.




Finalement, si on laisse de côté les descripteurs, je pense que les
choses se passent ainsi (c'est plutôt simple) :

Si obj fait référence à un objet quelconque et x est un nom de variable
valide, alors obj.x = expr (où expr est une expression quelconque) n'est
possible que si type(obj) possède la méthode __setattr__.


>
Dans ce cas, si x ne fait pas référence à un descripteur, obj.x = expr
est toujours intercepté par la méthode __setattr__ et donc

#--------------
obj.x = expr
#--------------

devient

#--------------
obj.__setattr__(x,expr)
(ou type(obj).__setattr__(obj,x,expr) qui lui est équivalent).
#--------------

1) Si le programmeur, n'a pas défini la méthode __setattr__ , par défaut
l'implémentation de __setattr__ fait que

#--------------
obj.__setattr__(x,expr)
#--------------

sera complètement équivalent à

#--------------
obj.__dict__('x') = expr
#--------------



<trivia>
obj.__dict__['x'] = expr
</trivia>


Donc, dans ce cas, obj.x = expr équivaut à obj.__dict__('x') = expr
(sauf pour x égal à __name__, __dict__, __bases__ [si obj est une
classe] ou __class__ [si obj est une instance], mais c'est un détail)



Sauf également si type(obj) définit des slots.
1 2