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

classe et données membres

16 réponses
Avatar
JBB
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?

10 réponses

1 2
Avatar
William Dode
On 19-12-2006, JBB wrote:
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?


oui avec les class new-age ;-)

class A(object):
__slots__=['name']

ne pas oublier le (object)


--
William Dodé - http://flibuste.net
Développeur informatique indépendant

Avatar
Eric Brunel
On Tue, 19 Dec 2006 17:30:31 +0100, William Dode wrote:

On 19-12-2006, JBB wrote:
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?


oui avec les class new-age ;-)

class A(object):
__slots__=['name']


... ce qui est considéré comme un abus de __slots__ et qui risque de poser
plein de problèmes par la suite, en particulier si on crée des
sous-classes de A. L'attribut __slots__ est prévu pour faire des
optimisations de mémoire dans le cas de petites classes avec peu
d'attributs, pas pour limiter les attributs possibles. Voir ici un message
de notre vénéré BDFL sur le sujet:
http://mail.python.org/pipermail/python-dev/2003-August/037542.html

Pour JBB, pourquoi veux-tu faire ça? Si tu ne veux pas rajouter d'attribut
dynamiquement depuiss l'extérieur de la classe, ne le fais pas. Où est le
problème?
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"


Avatar
William Dode
On 19-12-2006, Eric Brunel wrote:
On Tue, 19 Dec 2006 17:30:31 +0100, William Dode wrote:

On 19-12-2006, JBB wrote:
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?


oui avec les class new-age ;-)

class A(object):
__slots__=['name']


... ce qui est considéré comme un abus de __slots__ et qui risque de poser
plein de problèmes par la suite, en particulier si on crée des
sous-classes de A. L'attribut __slots__ est prévu pour faire des
optimisations de mémoire dans le cas de petites classes avec peu
d'attributs, pas pour limiter les attributs possibles. Voir ici un message
de notre vénéré BDFL sur le sujet:
http://mail.python.org/pipermail/python-dev/2003-August/037542.html


Tu lui diras pas hein ?

Merci pour l'info

--
William Dodé - http://flibuste.net
Développeur informatique indépendant



Avatar
Olivier Ravard
JBB wrote:
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?


Utiliser __getattr__

Avatar
Bruno Desthuilliers
J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?



class A(object):
_attribs = ['name',]
def __setattr__(self, name, value):
if name not in self._attribs:
raise AttributeError("can't set attribute %s" % name)
object.__setattr__(self, name, value)


Mais bon... Je ne vois vraiment pas l'intérêt de faire ça. Un
utilisateur de ta classe peut avoir une raison parfaitement valide de
vouloir ajouter un attribut à ta classe, et il te maudira en constatant
que tu l'en empêche arbitrairement.

Avatar
Bruno Desthuilliers
JBB wrote:

J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?



Utiliser __getattr__


Pour empêcher de *créer* un nouvel attribut ?


Avatar
jean-michel bain-cornu
Bonjour,
J'aimerai pouvoir empêcher d'ajouter des données membres/
Est ce que c'est possible de faire ça en python?


Je te propose le programme ci-après qui peut être une réponse me
semble-t-il. Il affiche 'methode x ok' et 'methode y ok'. Si on enlève
le commentaire de la ligne '##obj.test=...', une exception
AttributeError est déclenchée.
Ce n'est pas automatique, il faut appeler self.check() au début de
chaque méthode de la classe A, et l'exception ne se déclenche pas au
moment de l'attribution, mais au moment ou l'objet vérifie ses membres.
Mais c'est mieux que rien, et je n'ai pas trouvé d'autre moyen. Par
contre, c'est relativement propre.
Les contraintes sont de déclarer les membres dans l'__init__, et
d'appeler self.check() dans chaque méthode.
Ca peut servir si tu veux absolument préserver l'encapsulation dans
certains cas.
Ce qui serait bien, ce serait de pouvoir surdéfinir l'affectation d'un
membre, comme on le fait avec __eq__ par exemple pour le test d'égalité.
Dans ce cas, le self.check() pourrait être fait au moment de
l'affectation, et donc l'exception déclenchée si besoin. Quelqu'un
sait-il faire ça ?
A+
jm

class A:
def __init__(self):
self.name1= ''
self.name2= ''
self.lstMods= []
self.lstMods= dir(self)
def check(self):
if self.lstMods != dir(self):
raise AttributeError, 'attribution interdite !'
def methodx(self):
self.check()
print 'methode x ok'
def methody(self):
self.check()
print 'methode y ok'
obj= A()
obj.name1= 'truc1'
obj.methodx()
obj.name2= 'truc2'
##obj.test= 'toto'
obj.methody()

Avatar
Olivier Ravard
Bruno Desthuilliers wrote:
JBB wrote:

J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?



Utiliser __getattr__


Pour empêcher de *créer* un nouvel attribut ?
bien sûr.




Avatar
Olivier Ravard
Olivier Ravard wrote:
Bruno Desthuilliers wrote:
JBB wrote:

J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?



Utiliser __getattr__


Pour empêcher de *créer* un nouvel attribut ?
bien sûr.

Et pour une réponse plus complète, voici un petit exemple sur lequel

on peut discuter pour proposer une meilleure implémentation :

class Class1:

list_attr = {'name':None,
'other':None}

def __getattr__(self, attr):
if attr in Class1.list_attr:
return Class1.list_attr[attr]
else:
raise

def __setattr__(self, attr, value):
if attr in Class1.list_attr:
Class1.list_attr[attr]=value
else:
raise

if __name__=='__main__':
c = Class1()
c.name='toto'
print c.name, c.other

# cette ligne doit provoquer une xception
c.titi=1




Avatar
William Dode
On 21-12-2006, Olivier Ravard wrote:
Olivier Ravard wrote:
Bruno Desthuilliers wrote:
JBB wrote:

J'aimerai pouvoir empêcher d'ajouter des données membres/
exemple:
class A:
pass

x = A()
x.name = "toto" # crée une nouvelle donnée membre, uniquement sur
l'objet x.

je prefererais faire un truc du genre:

class A:
def __init__(self):
self.name = ""

x = A()
x.name = "toto" # ok
x.truc = 1 # génère une exception

Est ce que c'est possible de faire ça en python?



Utiliser __getattr__


Pour empêcher de *créer* un nouvel attribut ?
bien sûr.

Et pour une réponse plus complète, voici un petit exemple sur lequel

on peut discuter pour proposer une meilleure implémentation :

class Class1:

list_attr = {'name':None,
'other':None}

def __getattr__(self, attr):
if attr in Class1.list_attr:
return Class1.list_attr[attr]
else:
raise

def __setattr__(self, attr, value):
if attr in Class1.list_attr:
Class1.list_attr[attr]=value
else:
raise

if __name__=='__main__':
c = Class1()
c.name='toto'
print c.name, c.other

# cette ligne doit provoquer une xception
c.titi=1


Ton raise ne raise rien du tout ?
Une variante qui raise toute seule comme une grande

class Class1:

list_attr = {'name':None,
'other':None}

def __getattr__(self, attr):
return Class1.list_attr[attr]

def __setattr__(self, attr, value):
Class1.list_attr[attr]
Class1.list_attr[attr]=value


--
William Dodé - http://flibuste.net
Développeur informatique indépendant





1 2