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

Recherche sur les attributs d'un objet (suite)

22 réponses
Avatar
Francois
Bonjour à tous,

en fait, je souhaitais remonter un vieux post. Celui-ci :
http://groups.google.fr/group/fr.comp.lang.python/browse_thread/thread/7fde7231705c24e6
Mais il est trop vieux et n'existe plus dans mon lecteur de news. Donc
j'en créé un nouveau.

Le posteur original du message demandais comment obtenir les attributs
d'un objet. J'avais proposé de faire :

print obj.__dict__

On (Bruno en l'occurrence) avait rectifié en disant ceci :

« Ca ne renverra que les attributs de l'instance. Pour avoir tous les
attributs de l'objet, utilise dir(obj). »

Voici mes questions :

1) Je ne saisi pas trop la différence dans cette phrase entre "attributs
de l'instance" et "attributs de l'objet". Plus exactement, je ne saisi
pas trop la différence dans cette phrase entre "instance" et "objet".
Pour moi, un objet c'est toujours une instance de quelque chose. Donc
pour moi dire "attribut d'instance" ou "attribut d'objet" c'est censé
être la même chose. Est-ce possible d'avoir une explication sur ce point ?

2) J'ai l'impression que dir() affiche bien plus que les attributs d'un
objet. Par exemple avec ceci

#-----------------------
class Mc(object):
version = '1.0'

obj = Mc()
#-----------------------

dir(Mc) et dir(obj) me donneront (entre autres) 'version' comme
"attribut". Mais pour moi version est un attribut de Mc uniquement, mais
pas de obj. Bien sûr, obj.version va me renvoyer '1.0' mais lors de la
recherche de l'attribut, c'est dans l'objet classe Mc que version sera
trouvé et non dans l'objet obj. Est-ce correct ?

Dans ce cas, si obj désigne un objet quelconque (classe ou instance
etc...), existe-t-il une instruction pour afficher uniquement tous les
attributs qui appartiennent à obj et seulement ceux qui appartiennent à
obj ?

Merci d'avance.

--
François

10 réponses

1 2 3
Avatar
Méta-MCI \(MVP\)
Bonjour !

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un protocole
descripteur qui peut donner des attributs calculés ?

@-salutations

Michel Claveau
Avatar
Francois
Méta-MCI (MVP) a écrit :

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un protocole
descripteur qui peut donner des attributs calculés ?



Je suis désolé, mais je ne comprends pas du tout le sens de la question.
J'ai vraiment voulu dire ça dans mon message ?


--
François
Avatar
Bruno Desthuilliers
Francois a écrit :
Bonjour à tous,

en fait, je souhaitais remonter un vieux post. Celui-ci :
http://groups.google.fr/group/fr.comp.lang.python/browse_thread/thread/7fde7231705c24e6

Mais il est trop vieux et n'existe plus dans mon lecteur de news. Donc
j'en créé un nouveau.

Le posteur original du message demandais comment obtenir les attributs
d'un objet. J'avais proposé de faire :

print obj.__dict__

On (Bruno en l'occurrence) avait rectifié en disant ceci :

« Ca ne renverra que les attributs de l'instance. Pour avoir tous les
attributs de l'objet, utilise dir(obj). »

Voici mes questions :

1) Je ne saisi pas trop la différence dans cette phrase entre "attributs
de l'instance" et "attributs de l'objet".



Effectivement, la formulation n'était pas très heureuse. Traduction :
attributs appartenant en propre à l'instance, et attributs accessible
via l'objet.

Plus exactement, je ne saisi
pas trop la différence dans cette phrase entre "instance" et "objet".



C'est essentiellement une question de point de vue.

Pour moi, un objet c'est toujours une instance de quelque chose. Donc
pour moi dire "attribut d'instance" ou "attribut d'objet" c'est censé
être la même chose. Est-ce possible d'avoir une explication sur ce point ?



Tout objet est une instance de quelque chose, certes. Mais on
différencie généralement instance et classe (les classes étant instance
de leur métaclasse).

L'ensemble des attributs d'un objet se compose de l'ensemble des
attributs appartenant en propre à cet objet (généralement stockés dans
le __dict__) *et* de l'ensemble des attributs appartenant à sa classe
(et aux superclasses d'icelle). Sans compter ce qui peut être retourné
par __getattr__ ou __getattribute__ si ceux-ci ont été surchargés.

2) J'ai l'impression que dir() affiche bien plus que les attributs d'un
objet.



Non. A vrai dire, il n'est même pas garantie que dir() retourne
l'intégralité des attributs accessibles via l'objet.

Par exemple avec ceci

#-----------------------
class Mc(object):
version = '1.0'

obj = Mc()
#-----------------------

dir(Mc) et dir(obj) me donneront (entre autres) 'version' comme
"attribut". Mais pour moi version est un attribut de Mc uniquement, mais
pas de obj.



Dans la mesure où cet attribut est accessible via obj.version, c'est
*aussi* un attribut de l'objet 'obj' - même si cet attribut n'appartient
pas en propre à obj en tant qu'instance de Mc.

Bien sûr, obj.version va me renvoyer '1.0' mais lors de la
recherche de l'attribut, c'est dans l'objet classe Mc que version sera
trouvé et non dans l'objet obj. Est-ce correct ?



En l'occurrence, oui. Mais en tant qu'utilisateur de obj, ce n'est pas
ton problème. Les properties, par example, sont des attributs de la
classe, même si elles sont destinées à être interrogées sur l'instance.
Idem pour les méthodes.

Dans ce cas, si obj désigne un objet quelconque (classe ou instance
etc...), existe-t-il une instruction pour afficher uniquement tous les
attributs qui appartiennent à obj et seulement ceux qui appartiennent à
obj ?



obj.__dict__ - si obj à un __dict__, of course.
Avatar
Bruno Desthuilliers
Francois a écrit :
Méta-MCI (MVP) a écrit :

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un protocole
descripteur qui peut donner des attributs calculés ?



Je suis désolé, mais je ne comprends pas du tout le sens de la question.
J'ai vraiment voulu dire ça dans mon message ?




Non. Michel essaie d'attirer ton attention sur le fait que "attribut"
peut être compris de deux façons différentes:

- un objet référencé par le __dict__ (ou les slots) d'un autre objet
- un objet accessible par la syntaxe obj.attribut

Dans la mesure où Python propose pas mal de façons de customiser la
résolution d'attributs (les descripteurs - notamment les properties et
les méthodes -, __getattr__ et __getattribute__ ), les deux notions
peuvent être totalement disjointes.
Avatar
Francois
Bruno Desthuilliers a écrit :
Francois a écrit :
1) Je ne saisi pas trop la différence dans cette phrase entre
"attributs de l'instance" et "attributs de l'objet".



Effectivement, la formulation n'était pas très heureuse. Traduction :
attributs appartenant en propre à l'instance, et attributs accessible
via l'objet.



Ok, là je comprends parfaitement. Du coup, j'ai fait l'erreur (une
erreur de terminologie on va dire) tout au long de mon message.


L'ensemble des attributs d'un objet se compose de l'ensemble des
attributs appartenant en propre à cet objet (généralement stockés dans
le __dict__) *et* de l'ensemble des attributs appartenant à sa classe
(et aux superclasses d'icelle). Sans compter ce qui peut être retourné
par __getattr__ ou __getattribute__ si ceux-ci ont été surchargés.



D'accord. Dans mon esprit, quand je disais "les attributs d'un objet" je
pensais aux "attributs appartenant en propre à l'objet" pour reprendre
ta formulation. Or, si je comprends bien la convention veut plutôt que
"attributs d'un objet" signifie "attributs accessibles via l'objet".
C'est bon à savoir ça m'évitera quelques incompréhensions.


2) J'ai l'impression que dir() affiche bien plus que les attributs
d'un objet.



Non. A vrai dire, il n'est même pas garantie que dir() retourne
l'intégralité des attributs accessibles via l'objet.



Pourtant dir() retourne un paquet de trucs. Mais tu as raison. Par
exemple, pour une classe Mc l'attribut Mc.__bases__ n'est pas listé par
dir(Mc). C'est de la rétention d'information cette fonction dir() ! :-)


Bien sûr, obj.version va me renvoyer '1.0' mais lors de la recherche
de l'attribut, c'est dans l'objet classe Mc que version sera trouvé et
non dans l'objet obj. Est-ce correct ?



En l'occurrence, oui. Mais en tant qu'utilisateur de obj, ce n'est pas
ton problème. Les properties, par exemple, sont des attributs de la
classe, même si elles sont destinées à être interrogées sur l'instance.
Idem pour les méthodes.



Oui, je comprends le point de vue de "l'utilisateur" qui voit
essentiellement des objets instances qu'il manipule avec des méthodes.
Ce point de vue renforce l'idée que "attributs d'objet" = "attributs
accessibles via l'objet".


Dans ce cas, si obj désigne un objet quelconque (classe ou instance
etc...), existe-t-il une instruction pour afficher uniquement tous les
attributs qui appartiennent à obj et seulement ceux qui appartiennent
à obj ?



obj.__dict__ - si obj à un __dict__, of course.



Ok. Encore que __dict__ aussi semble faire un peu de rétention
d'informations.

Par exemple si obj est une instance de classe alors obj.__dict__ ne
contient pas __dict__ (bon ça c'est un peu normal car un dictionnaire
que se contient lui-même ça serait bizarre), mais il ne contient pas
__classe__

Si Mc est une classe Mc.__dict__ ne contient pas __bases__ (tout comme
dir()) mais par contre il contient __dict__ (c'est-à-dire il se contient
lui-même !?).

Merci beaucoup pour la réponse.


--
François
Avatar
Eric Brunel
On Fri, 22 Aug 2008 09:19:59 +0200, Francois wrote:

Méta-MCI (MVP) a écrit :

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un protocole
descripteur qui peut donner des attributs calculés ?



Je suis désolé, mais je ne comprends pas du tout le sens de la question.
J'ai vraiment voulu dire ça dans mon message ?



C'est simplement qu'apparemment, tu ne saisis pas (encore...) très bien le
modèle objet de Python: un "attribut", en fait, ça ne veut pas dire grand
chose, en tous cas au sens où tu sembles l'entendre.

Exemple:
---------------------------------------
class Foo(object):
def get_p(self):
return 42
def set_p(self, p):
print "m'en fous..."
p = property(get_p, set_p)

bar = Foo()
print bar.p
bar.p = 72
print bar.p
---------------------------------------

p est-il un "attribut" de Foo? de bar? de quoi en fait...? Les choses ne
sont pas forcément claires en ce qui concerne les "attributs". Par
exemple, en Python, la distinction attribut/méthode n'existe pas: une
méthode, c'est juste un attribut exécutable qui implémente le protocole
descripteur. De même, la distinction entre attribut d'instance et attribut
de classe n'est pas hyper-tranchée non plus: tu peux avoir des attributs
calculés définis au niveau de la classe qui vont renvoyer des valeurs
différentes en fonction de l'instance. Ou pas, comme dans l'exemple
ci-dessus... Donc demander à ne récupérer que les attributs d'une instance
n'a pas forcément grand sens... Je pense que c'est ce que Michel voulait
dire (il s'empressera de ma corriger si je me fourvoies...).

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Avatar
Francois
Bruno Desthuilliers a écrit :
Francois a écrit :
Méta-MCI (MVP) a écrit :

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un
protocole descripteur qui peut donner des attributs calculés ?



Je suis désolé, mais je ne comprends pas du tout le sens de la
question. J'ai vraiment voulu dire ça dans mon message ?




Non. Michel essaie d'attirer ton attention sur le fait que "attribut"
peut être compris de deux façons différentes:

- un objet référencé par le __dict__ (ou les slots) d'un autre objet
- un objet accessible par la syntaxe obj.attribut

Dans la mesure où Python propose pas mal de façons de customiser la
résolution d'attributs (les descripteurs - notamment les properties et
les méthodes -, __getattr__ et __getattribute__ ), les deux notions
peuvent être totalement disjointes.



Ok, je comprends. En customisant (avec __getattr__ et getattribute__
etc) on peut rendre les deux notions disjointes. Mais, sans trop vouloir
rentrer dans le détail, ça peut avoir un intérêt ? (sûrement que oui)
Je peux comprendre qu'on veuille «surcharger» les références et
affectations d'attributs pour que ça affiche des messages d'info par
exemple pour trouver un bug. Mais customiser au point que l'on ne passe
plus par __dict__ j'ai du mal à imaginer un intérêt.


--
François
Avatar
Francois
Eric Brunel a écrit :

C'est simplement qu'apparemment, tu ne saisis pas (encore...) très bien
le modèle objet de Python:



Et oui, je crains que tu aies raison. Mais j'y travaille. :-)

Merci pour ton message, que je vais bien étudier quand je pourrais,
auquel cas je pense que je reviendrai à la charge. Mais en attendant, je
voulais en venir de suite à un point de ton message...


> De même, la distinction entre attribut d'instance et
attribut de classe n'est pas hyper-tranchée non plus: tu peux avoir des
attributs calculés définis au niveau de la classe qui vont renvoyer des
valeurs différentes en fonction de l'instance. Ou pas, comme dans
l'exemple ci-dessus... Donc demander à ne récupérer que les attributs
d'une instance n'a pas forcément grand sens...



... ben en fait, dans mon esprit, les choses étaient tranchées avant que
je ne lance ce post. Je voyais les choses ainsi :

un objet obj possède un espace de noms que j'appelle N, qui contient (ou
pas) des noms de variables (on peut avoir N = vide). Pour moi, les
attributs de l'objet obj sont tous les objets liés aux noms de variables
appartenant à N.

Donc dans mon esprit, avec cette façon de voir, il y avait une
distinction très tranchée et nette entre attribut d'une instance donnée
et attribut de la classe.

Mais, ce n'est pas comme cela qu'il faut concevoir le modèle objet ?

--
François
Avatar
Bruno Desthuilliers
Francois a écrit :
Bruno Desthuilliers a écrit :
Francois a écrit :
Méta-MCI (MVP) a écrit :

Plutôt qu'une réponse, j'ai une question :
- est-il vraiment judicieux de faire une recherche, avec un
protocole descripteur qui peut donner des attributs calculés ?



Je suis désolé, mais je ne comprends pas du tout le sens de la
question. J'ai vraiment voulu dire ça dans mon message ?




Non. Michel essaie d'attirer ton attention sur le fait que "attribut"
peut être compris de deux façons différentes:

- un objet référencé par le __dict__ (ou les slots) d'un autre objet
- un objet accessible par la syntaxe obj.attribut

Dans la mesure où Python propose pas mal de façons de customiser la
résolution d'attributs (les descripteurs - notamment les properties et
les méthodes -, __getattr__ et __getattribute__ ), les deux notions
peuvent être totalement disjointes.



Ok, je comprends. En customisant (avec __getattr__ et getattribute__
etc) on peut rendre les deux notions disjointes.



Elles le sont déjà, au moins partiellement.

Mais, sans trop vouloir
rentrer dans le détail, ça peut avoir un intérêt ?



obj.method()

(sûrement que oui)



Et oui.

Je peux comprendre qu'on veuille «surcharger» les références et
affectations d'attributs pour que ça affiche des messages d'info par
exemple pour trouver un bug. Mais customiser au point que l'on ne passe
plus par __dict__ j'ai du mal à imaginer un intérêt.



Moi pas. Pense à une classe exposant des données "externes" (SGBDR,
LDAP, CSV, XML, whatever...) sous forme d'un objet Python. Tu ne
souhaites pas forcément passer ton temps à transformer le format de
données que tu reçois effectivement (celui du SGBDR, du LDAP etc) en
attributs d'instance et réciproquement. Il est parfois plus simple de
conserver les données "brutes" dans leur format d'origine, et de les
exposer comme des attributs 'ordinaires' (via un attribut calculé).

D'une manière plus large, c'est le principe de base du pattern Proxy et
de la composition/délégation, et, au dela, du découplage
interface/implémentation en général.
Avatar
Francois
Merci bien pour vos réponses respectives.

Effectivement, je comprends bien l'erreur qui consiste à dire que seuls
les objets référencés dans l'espace de nom de obj sont des attributs de
obj. En effet, une méthode n'est jamais dans l'espace de nom d'une
instance et pourtant on parle bien de "méthodes liées à un objet
instance". Si C est une classe dans laquelle on définit une méthode m et
si o1 et o2 sont deux instances de C, alors les objets o1.m et o2.m sont
tous les deux des objets méthodes bien distincts, et sont bien des
méthodes liées chacune respectivement à o1 et o2, donc on peut vraiment
dire que ce sont des attributs respectivement de o1 et o2 (vu qu'ils
sont liés avec eux).

En résumé :

« m attribut de C » : pas de sens.
« C.m attribut de C » : oui c'est un objet méthode non liée
« o1.m attribut de o1 » : oui c'est un objet méthode liée à o1

Désolé pour ces trivialités. Je confondais la notion d'attribut (issu du
*modèle* objet) avec la notion d'espace de nom qui relève plutôt de
*l'implémentation* du modèle objet en Python.

Merci bien pour votre aide.

--
François
1 2 3