Jusqu'ici, nous avons observé que les attributs auront des valeurs redéfinissables pour chaque objet. Mais qu'en est-il si l'on souhaite avoir une valeur partagée entre plusieurs instances ou à l'inverse gagner un peu en définissant spécifiquement les valeurs pour une instance.
Nous avons manqué un peu de précision en définissant précédemment les attributs. Nous avons présenté notre attribut essai de la même façon alors qu'il est apparu dans deux contextes différents : celui de la racine de la classe, et celui de la méthode. Nous avons mentionné que cet attribut était lié à l'instance, ce qui n'est pas pas tout à fait juste. Prenons le point suivi pour aborder le sujet : si à l'inverse, nous souhaitions que la même valeur soit partagée par plusieurs instances, la syntaxe de l'attribut devrait être un peu différente : on le définira en début de classe en dehors de toute méthode ou on le préfixera avec le nom de la classe de manière que l'attribut y soit explicitement associé, et non pas aux instances :
class MaClasse : essai = "ok" def affiche(self): print essai objet = MaClasse() objet2 = MaClasse() objet.affiche() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in affiche NameError: global name 'essai' is not defined
On voit dans cet exemple qu'un petit problème se pose : il n'est pas possible d'accéder à l'attribut essai à partir de la méthode affichée. La première solution qui pourrait nous venir à l'esprit serait d'utiliser le mot clé self pour spécifier l'appartenance de l'attribut, mais voici :
class MaClasse : essai = "ok" def affiche(self): print self.essai objet = MaClasse() objet.affiche() > ok objet2 = MaClasse() objet2.affiche() > ok objet2.essai = "wow" objet2.affiche() > wow objet.affiche() > ok
Nous nous retrouvons alors dans la même configuration que précédemment et ne résolvons pas notre problème : l'attribut est associé à l'instance, et n'est pas partagé entre celle-ci.
La solution consiste à associer explicitement l'attribut à la classe en le pointant comme tel. Au lieu d'utiliser le mot-clé self, nous utiliserons alors le nom de la classe pour bien préciser que c'est à son niveau que les opérations vont s'effectuer.
>>> class MaClasse: def __init__(self): MaClasse.essai = "ok" objet = MaClasse() objet2 = MaClasse() print objet.essai > ok print objet2.essai > ok print MaClasse.essai > ok MaClasse.essai = "wow" print objet.essai > wow print objet2.essai > wow
Ici, les deux instances partagent donc bien le même attribut et changer la valeur de cet attribut en la préfixant du nom de la classe, même au moment de la réaffectation, permet bien de spécifier que ce n'est pas au niveau de l'instance que les choses se jouent et que par conséquent, toutes les instances hériteront de cette nouvelle valeur.
Si les choses ne sont pas clairement définies, il est possible de se retrouver avec de petites surprises. Continuons dans la foulée des lignes précédentes :
class MaClasse : essai = "ok" def affiche(self): print self.essai objet = MaClasse() objet.affiche() > ok objet2 = MaClasse() objet2.affiche() > ok objet2.essai = "wow" objet2.affiche() > wow objet.affiche() > ok print objet2.essai > wow MaClasse.essai = "test" objet.affiche() > test objet2.affiche() > wow
Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.
Vous devriez rafraîchir la page.