Voila comment ajouter un attribut couleur à la classe Point :
>>> class Point : ... "Définition d’un point mathématique" ... couleur = "Rouge" ...
Pour dire que couleur est un attribut privé, on précède son nom de deux espaces soulignés :
>>> class Point : ... "Définition d’un point mathématique" ... __couleur = "Rouge"
Un espace souligné signifie que l'attribut est protégé.
Il est rare de rencontrer des attributs privés, et la convention d'un _ suffit à indiquer la nature interne de l'attribut (cette convention est aussi valable pour les méthodes internes).
Pour accéder aux attributs, on utilise le point . :
>>> p = Point() >>> p.couleur 'rouge'
Les attributs d'un objet sont modifiables :
>>> p.couleur = p.couleur+" vif"
Définissons un objet Rectangle, caractérisé par son point supérieur gauche, sa longueur et sa largeur :
>>> class Rectangle: >>> "définition d'une classe de rectangles" ... >>> boite = Rectangle() >>> boite.largeur = 50.0 >>> boite.hauteur = 35.0
Reste à définir le coin : cela ne pose aucun problème d'avoir ici un objet...
>>> boite.coin = Point() >>> boite.coin.x = 12.0 >>> boite.coin.y = 27.0
Si couleur est privé (__couleur, donc), alors on peut toujours y accéder dans les méthodes de la classe possédant cet attribut :
>>> class Point : ... "Définition d'un point mathématique" ... __couleur = "Rouge" ... def affiche_couleur(self) : ... print self.__couleur ... >>> p=Point() >>> p.affiche_couleur() rouge
...mais on n'y a plus accès à l'extérieur de la classe :
>>> p.__couleur Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: Point instance has no attribute '__couleur'
Contrairement à d’autres langages objets, ces protections restent déclaratives : il est tout à fait possible d’accéder à un attribut privé, en faisant appel à son nom préfixé.
>>> pt=Point() >>> pt._Point__couleur 'Rouge'
Il est possible de lire ou de modifier un attribut dynamiquement avec les fonctions :
C'est un système de propriété pour simplifier l'écriture des accesseurs simples :
>>> class Livre(object): ... def __init__(self): ... self._titre = u"titre" ... def _getTitre(self): ... return self._titre ... def _setTitre(self, valeur): ... self._titre = value.titre() ... titre = property(fget = _getTitre, ... fset = _setTitre, ... doc = "titre") ... >>> unLivre = Livre() >>> unLivre.titre u"titre" >>> unLivre.titre = u"Les chants de Maldoror" >>> unLivre.titre u"Les chants de Maldoror"
Si l’on souhaite rajouter un attribut à l’objet p...il n’y a qu’à le faire ! Le bout de code suivant ne posera pas de problème :
>>> p.abscisse = 10
Cependant, si l’on instancie un deuxième point :
>>> p2 = Point()
et que l’on demande la valeur de l’abscisse pour cet autre point (p2.abscisse), une exception sera levée (du genre : l'instance p2 ne possède pas d'attribut 'abscisse').
Bref, la classe Point n’a pas été modifiée par l’ajout d’un nouvel attribut à l’une de ses instances.
NB. Cette pratique est faisable, mais est à éviter.
Supposons que p soit un objet ayant un attribut x. L'instruction
>>> x = p.x
ne pose aucun problème : il n'y a pas de conflit entre la variable x et l'attribut x de l'objet p, qui possède son propre espace de noms.
Pour en savoir plus, aller ici.