Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

question de programmation objet

0 views
Skip to first unread message

laurent FRANCOIS

unread,
Nov 26, 2009, 7:42:56 AM11/26/09
to
Bonjour,

Voila j'ai beaucoup de mal � m'y retrouver dans les espaces de
nommage. Un objet appartient � quel espace de nommage?
Comment faire pour le mettre dans un espace de nommage donn�?
Comment faire pour acc�der � un objet quant on n'arrive pas �
comprendre dans quel espace de nommage il est?
Quand je lis du code j'ai la plus part du temps � voir dans
quel espace de nommage appartient tel ou tel objet. (sauf si c'est archi
basique ie que des objets global)

Par exemple:

class Foo(object):
... colLabels = ["Forst", "Last"]
... def GetColLabelValue(self, col):
... return self.colLabels[col]

colLabels est un attribut de classe (C'est �a?). et je d�couvre que
je peux y acc�der par self.colLabels (C'est un attribut de l'instance
de Foo?). Je suis perplexe. Je n'arrive m�me pas � expliquer ce que je
ne comprends pas.

Si encore on avait cod�:

class Foo(object):
... def __init__(self):
... self.colLabels = ["Forst", "Last"]
... def GetColLabelValue(self, col):
... return self.colLabels[col]

L� pas de probleme. Je crois avoir compris. Lors de l'instanciation
__init__ cr�e un attribut d'instance (colLabels) qui "pointe" vers la
liste ["Forst", "Last"]

Et si je code:

class Foo(object):
... colLabels = ["Forst", "Last"]
... def GetColLabelValue(self, col):
... return colLabels[col]
...
>>> foo = Foo()
>>> foo.GetColLabelValue(1)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 4, in GetColLabelValue
NameError: global name 'colLabels' is not defined


L� je suis encore plus perplexe. J'ai l'impression
qu'il y a quelque chose de basique que je n'ai pas
compris dans la POO. Est-ce qu'il y en a parmi vous
qui voient quel est mon probleme?

Merci

Bruno Desthuilliers

unread,
Nov 26, 2009, 9:05:56 AM11/26/09
to
laurent FRANCOIS a �crit :

> Bonjour,
>
> Voila j'ai beaucoup de mal � m'y retrouver dans les espaces de
> nommage. Un objet appartient � quel espace de nommage?

Si tu poses la question en ces termes, tu risques effectivement d'avoir
du mal � t'y retrouver !-)

Un objet "n'appartient" pas � un espace de nommage - ce sont les _noms_
qui appartiennent � un espace de nommage. En Python, une "variable"
n'est pas une �tiquette sur un espace m�moire, c'est l'association d'un
nom et d'une *r�f�rence* sur un objet. Plusieurs noms, qu'ils
appartiennent au m�me espace de nommage ou non, peuvent r�f�rencer
simultan�ment le m�me objet.

En fait, le plus simple est de consid�rer les espaces de nommage comme
des dicts nom=>r�f�rence sur un objet. Et c'est d'ailleurs souvent ce
qu'ils sont effectivement.

> Comment faire pour le mettre dans un espace de nommage donn�?

cf ci-dessus. Tout ce que tu peux "mettre" dans un espace de nommage,
c'est un nom.

> Comment faire pour acc�der � un objet quant on n'arrive pas �
> comprendre dans quel espace de nommage il est?

L� c'est autre chose.

> Quand je lis du code j'ai la plus part du temps � voir dans
> quel espace de nommage appartient tel ou tel objet. (sauf si c'est archi
> basique ie que des objets global)
>
> Par exemple:
>
> class Foo(object):
> ... colLabels = ["Forst", "Last"]
> ... def GetColLabelValue(self, col):
> ... return self.colLabels[col]
>
> colLabels est un attribut de classe (C'est �a?).

Oui. En fait, les classes �tant elles-m�me des objets (instances de leur
m�taclasse, par d�faut 'type'), c'est un attribut de l'objet "Foo". Si
tu inspectes Foo.__dict__, tu y trouvera "colLabels" et "GetColLabelValue".

> et je d�couvre que
> je peux y acc�der par self.colLabels (C'est un attribut de l'instance
> de Foo?)

Non. Voir ci-dessous.

>. Je suis perplexe. Je n'arrive m�me pas � expliquer ce que je
> ne comprends pas.

C'est souvent le cas quand on ne comprends pas !-)

La r�gle de r�solution d'attributs - telle qu'impl�ment�e par
object.__getattribute__ - est la suivante:

1/ regarder si le nom existe dans le __dict__ de la classe ou d'une des
classes parents. Si oui ET que l'attribut correspondant est un
descripteur, retourner le r�sultat de l'appel � sa m�thode __get__.

2/ Sinon, regarder si le nom existe dans le __dict__ (ou les __slots__)
de l'instance. Si oui, retourner l'attribut correspondant.

3/ Sinon, regarder si la classe (ou une des classes parent) d�finit la
methode __getattr__. Si oui, retourner le r�sultat de l'appel � __getattr__

4/ Sinon, regarder si le nom existe dans le __dict__ de la classe ou
d'une des classes parents. Si oui, retourner l'attribut correspondant

5/ si toutes les m�thodes pr�c�dentes ont �chou�es, lever un AttributeError


> Et si je code:
>
> class Foo(object):
> ... colLabels = ["Forst", "Last"]
> ... def GetColLabelValue(self, col):
> ... return colLabels[col]

Tu a un NameError.

> ...
> >>> foo = Foo()
> >>> foo.GetColLabelValue(1)
> Traceback (most recent call last):
> File "<input>", line 1, in <module>
> File "<input>", line 4, in GetColLabelValue
> NameError: global name 'colLabels' is not defined

Bingo.

>
> L� je suis encore plus perplexe. J'ai l'impression
> qu'il y a quelque chose de basique que je n'ai pas
> compris dans la POO.

Ce n'est pas un probl�me de POO, c'est un probl�me de port�e et de
mod�le d'ex�cution.

En Python, � peu pr�s tout se passe � l'ex�cution. Entre autres,
l'instruction "class" et l'instruction "def" sont des instructions
ex�cutables. Lors de l'ex�cution de "class", un espace de nommage
temporaire (correspondant au bloc 'class') est cr��, qui contient tous
les noms d�finis dans ce bloc ET � ce niveau l� - soit par une
assignation, soit par un "def". Cet espace de nommage (un dict en fait)
est ensuite pass� - avec le nom de la classe et la liste des classes
parentes - � la m�thode __new__ de la m�taclasse, laquelle m�thode se
charge de retourner le nouvel objet class, d�ment initialis� avec les
noms en question comme attributs. C'est ainsi que, dans ton example,
colLabels (un objet liste) et GetColLabelValue (un objet function)
deviennent des attributs de la classe Foo.

Par contre, les noms pr�alablement d�finis dans cet espace de nommage ne
sont pas "captur�s" par les fonctions d�finies dans ce m�me espace. Donc
quand GetColLabelValue est appel�e, c'est la r�gle normale qui
s'applique pour r�soudre "colLabels" - � savoir l'espace de nommage
local, puis l'espace de nommage "global" (c'est � dire celui du
module)[1]. Comme le nom en question n'est d�fini dans aucun de ses deux
espaces de nommages, tu a un NameError.

Il faut bien comprendre que pour une fonction, le fait d'�tre d�finie
dans un bloc "class" ne change rien en soi. Tu a exactement le m�me
fonctionnement en d�finissant ta fonction en dehors de la classe et en
l'assignant � la classe ensuite. Ce qui "transforme" la fonction en
"m�thode" (une m�thode n'�tant rien d'autre qu'un objet appelable avac
comme attributs la fonction, la classe et l'instance) est simplement une
application du protocole descripteur (et c'est d'ailleurs une des
raisons d'�tre de ce protocole - fournir un m�canisme g�n�rique pour les
attributs calcul�s).

Accessoirement, tout ce mode de fonctionnement est propre au mod�le
objet de Python, qui est tr�s particulier.

[1] je passe sur le cas des fermetures, puisque ta fonction n'en est pas
une.


HTH

0 new messages