J'ai vu que il y a peu, le tutoriel python a été agrémenté de quelques chapitres sur la POO coté développeur, et le second chapitre parle des propriétés. En fait j'aimerais savoir l'utilité des propriété par rapport aux méthodes spéciales ? En effet je ne vois pas pourquoi les utiliser, sachant qu'elle ne sont pas 'parfaite' :
class Test(object):
def __init__(self,a):
self._a = a
def _get_a(self):
return self._a
def _set_a(self,val):
if val < 0:
val = 0
self._a = 0
a = property(_get_a,_set_a)
c = Test(-15)
# ici c.a vaut -15
# de plus je peux 'tricher' en faisant c._a = -18 et c.a vaudra -18 (au lieu de 0)
J'ai cherché dans le manuel de référence python mais je n'ai pas trouvé grand chose dessus en fait, c'est pour ça que je pose la question ! (Le seul passage que j'ai vu dit "The property() function is implemented as a data descriptor. Accordingly, instances cannot override the behavior of property.")
Rien à voir avec les propriétés, là, mais plus avec le manque de contrôle dans le constructeur.
Certes, mais bon avec les méthodes spéciales le problème aurait été réglé
Citation
# de plus je peux 'tricher' en faisant c._a = -18 et c.a vaudra -18 (au lieu de 0)
Si tu doubles l'underscore devant l'attribut (__a), il devient beaucoup plus compliqué de "tricher" (à cause du name mangling).
Oui je connaissais pas le 'name mangling', mais reste que je peux tout de même accéder à l'attribute ? (bon ok il faut s'amuser avec les noms de variables mais certes).
En fait je ne voulais pas du tout dire que les propriétés sont inutiles (enfin je me suis quand même mal exprimé en relisant mon post ), mais plutôt quelle sont leurs avantages par rapports aux méthodes spéciales ? (__getattribute__,__getattr__,__setattr__,__delattr__) J'ai tout simplement commencer à prendre l'habitude d'utiliser ces méthodes pour mes classes (pour le peu que je fais de POO ), et donc j'aimerais savoir si c'était une mauvaise habitude ? Ou si les deux étaient équivalente (d'un point de vue encapsulation) ?
Pour ce qui est de la gestion des attributs, les propriétés permettent une gestion plus fine que les méthodes __getattr__, etc. : tu peux facilement implémenter des contrôles différents selon les attributs auxquels tu cherches à accéder.
Pour le reste, elles permettent aussi d'interdire facilement l'accès "en écriture" sur un attribut (il suffit de ne pas spécifier de setter pour une propriété donnée). Elles permettent aussi de créer des pseudo-attributs qui n'ont pas forcément de réelle existence (en mémoire, je veux dire) dans la classe : par exemple, je peux créer une propriété 'aire' sur une classe Rectangle, seulement accessible par son getter (returnself.__hauteur*self.__largeur), sans avoir à créer d'attribut __aire. L'intérêt de cette propriété est surtout qu'elle allège la syntaxe, et rend la classe plus intuitive à utiliser en Python.
Pour ce qui est de la gestion des attributs, les propriétés permettent une gestion plus fine que les méthodes __getattr__, etc. : tu peux facilement implémenter des contrôles différents selon les attributs auxquels tu cherches à accéder.
Pour le reste, elles permettent aussi d'interdire facilement l'accès "en écriture" sur un attribut (il suffit de ne pas spécifier de setter pour une propriété donnée). Elles permettent aussi de créer des pseudo-attributs qui n'ont pas forcément de réelle existence (en mémoire, je veux dire) dans la classe : par exemple, je peux créer une propriété 'aire' sur une classe Rectangle, seulement accessible par son getter (returnself.__hauteur*self.__largeur), sans avoir à créer d'attribut __aire. L'intérêt de cette propriété est surtout qu'elle allège la syntaxe, et rend la classe plus intuitive à utiliser en Python.
Tout ça on peut le faire avec les méthodes spéciales non ?
Par exemple :
class Rect(object):
def __init__(self,larg,haut,x): # x variable inutile
self.l, self.h, self.x = larg, haut, x
def __getattribute__(self,name):
return object.__getattribute__(self,name)
def __getattr__(self,name):
if name == 'aire':
return self.l * self.h
def __setattr__(self,name, val):
if name == 'l' or name == 'h':
if val < 0:
val = 0
elif name == 'x':
if type(val) != type(''):
val = ''
else:
print('Attribut immutable !')
return
object.__setattr__(self,name,val)
>>> c = Rect(12,18,0)
>>> c.l,c.h,c.x
(12, 18, '')
>>> c.aire
216
>>> c.h = -48
>>> c.h, c.aire
(0,0)
Bon là j'y ai été un peu brutalement (si l'argument n'est pas correctement, on met un argument par défaut), mais j'aurais très bien pu faire autre chose (enfin je pense que tu t'en doutes ).
Après je dois avoué que pour l'attribut aire cela oblige a créé un cas spécial dans __setattribute__, mais vu qu'il n'a besoin d'être créé qu'une fois pour tous les 'pseudo-attributs' !
Si ce n'est pas de ça que tu parlais dans ton post, mea-culpa pour ce post idiot
Je suis d'accord, tu peux faire tout ça en utilisant les méthodes spéciales, mais tu perds en lisibilité en collant un branchement conditionnel.
Si ta classe doit avoir une dizaine de pseudo-attributs différents (prends par exemple la classe Rect de Pygame qui permet d'influencer sa taille/position en jouant sur les coordonnées des points "topleft", "bottomright", "center" ou plus indépendamment les coordonnées "top", "left", "bottom", "right", "x", "y", "centerx", "centery" et les valeurs "area", "size" (c'est une paire), "width", "height"), tes branchements conditionnels deviennent énormes, et beaucoup moins faciles à maintenir.
Je suis d'accord, tu peux faire tout ça en utilisant les méthodes spéciales, mais tu perds en lisibilité en collant un branchement conditionnel.
Si ta classe doit avoir une dizaine de pseudo-attributs différents (prends par exemple la classe Rect de Pygame qui permet d'influencer sa taille/position en jouant sur les coordonnées des points "topleft", "bottomright", "center" ou plus indépendamment les coordonnées "top", "left", "bottom", "right", "x", "y", "centerx", "centery" et les valeurs "area", "size" (c'est une paire), "width", "height"), tes branchements conditionnels deviennent énormes, et beaucoup moins faciles à maintenir.
Je vois ce que tu veux dire mais avec les propriétés cela m'oblige à créer autant de fonction (en double), est ce vraiment plus lisible ? (Je n'ai pas vraiment utilisé les propriétés, mais je trouves que avoir un grand nombre de fonction pour n'est pas forcément plus lisible qu'un grand branchement conditionnel (dans ce cas précis je parle)) De plus je peux gérer 2 attributs de la même façon (dans mon exemple l et h), est ce que on peut le faire avec les propriétés ? Enfin bon je vois déjà un peu mieux quel peut être l'utilité des propriétés, merci à toi, je pense que j'utiliserais l'un ou l'autre en fonction
Je vois ce que tu veux dire mais avec les propriétés cela m'oblige à créer autant de fonction (en double), est ce vraiment plus lisible ?
Personnellement je préfère avoir plusieurs petites méthodes plutôt qu'une seule, grosse : c'est beaucoup plus facile à gérer si tu dois dériver ta classe, par exemple.
Citation : Holt
De plus je peux gérer 2 attributs de la même façon (dans mon exemple l et h), est ce que on peut le faire avec les propriétés ?
Non, en effet.
Citation : Holt
Enfin bon je vois déjà un peu mieux quel peut être l'utilité des propriétés, merci à toi, je pense que j'utiliserais l'un ou l'autre en fonction
Oui, ça dépend avant tout de ce à quoi est destinée ta classe.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.