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

Une définition d'attribut de classe me pose problème

5 réponses
Avatar
Méta-MCI
Bonjour !

Regardez ce code :

class hh(object):
def __init__(self):
pass

class cla(object):
def __init__(self, **args):
self.h=hh()
for k,v in args.items():
setattr(self,k,v)

#--là, ça marche--------------------------------
a=cla( titi='oiseau', minet='chat')
a.h.bras = 'membre'
a.h.foie = 'organe'

print a.titi
print a.minet
print a.h.bras
print a.h.foie

#--ici, ça ne marche pas---------------------
b=cla( titi='dinosaure', minet='mammifère', h.bras='membre',
h.foie='organe')

print b.titi
print b.minet
print b.h.bras
print b.h.foie



Y a-t'il un moyen de contourner cette limitation, due aux dictionnaires ?

Merci d'avance


Michel Claveau

5 réponses

Avatar
Bruno Desthuilliers
Bonjour !

Regardez ce code :

class hh(object):
def __init__(self):
pass

class cla(object):
def __init__(self, **args):
self.h=hh()
for k,v in args.items():
setattr(self,k,v)


Tu devrais tester si par hasard tu n'écrase pas un attribut par accident...

#--là, ça marche--------------------------------
a=cla( titi='oiseau', minet='chat')
a.h.bras = 'membre'
a.h.foie = 'organe'

print a.titi
print a.minet
print a.h.bras
print a.h.foie

#--ici, ça ne marche pas---------------------


<ot>
"ne marche pas" est la description la plus inutile possible d'un problème.
</ot>

b=cla( titi='dinosaure', minet='mammifère', h.bras='membre',
h.foie='organe')


=> SyntaxError: keyword can't be an expression



Y a-t'il un moyen de contourner cette limitation, due aux dictionnaires ?


Ce n'est pas dû aux dictionnaires. Tu peux parfaitement utiliser
'h.truc' comme clé d'un dict.

la solution propre - dans la mesure où ce que tu essaie de faire
implique que le client sait que cla a un attribut h de type hh - est
évidemment de passer directement l'instance de hh:

class cla(object):
def __init__(self, **args):
for k,v in args.items():
setattr(self,k,v)

a = cla(titi='titi', h=h(totoB))

Avatar
Michel Claveau
Re !

si par hasard tu n'écrase pas un attribut par accident


Oui, mais, là, je veux que ça écrase.


a = cla(titi='titi', h=h(totoB))


Ok, mais :
- je pense qu'il faudrait écrire a=cla(titi='titi', h=hh(totoB))
- c'est trop dur à lire, pour mon public ;
- cela m'oblige à revoir l'implémentation de la classe hh








--
@-salutations

Michel Claveau

Avatar
Maric Michaud
Michel Claveau wrote:

- je pense qu'il faudrait écrire a=cla(titi='titi', h=hh(totoB))
- c'est trop dur à lire, pour mon public ;


Vous pouvez toujours écrire :

h=hh()
h.totoB
a=cla(titi='titi', h=h)

- cela m'oblige à revoir l'implémentation de la classe hh


Peut-être il faudrait... Pourquoi cette classe n'offre pas la possibilité
d'initialiser ses membres ?

Si ce n'est pas possible, mettons que vous n'avez pas la main sur cette
classe par exemple, la meilleure solution est plutôt quelque chose du
genre :

class cla(object):
def __init__(self, minet='chat', bras=None, foie=None):
self.minet = minet
self.h=hh()
if bras is not None : self.h.bras = bras
if foie is not None : self.h.foie = foie

Il est préférable d'éviter les arguments variables, pour des raisons de
documentation de l'API de la classe, ceci dit, si vraiment le nombre de
variables à initialiser dans la classe Hh est potentiellement très grand,
je pencherais vers :

class Cla(object):
def __init__(self, minet = None, **kwargs):
"""All non explicit named arguments will serve to initialize the
Hh properties of the instance.
for example :
c = Cla(minet='chat', foie='foie')
c.h.foie == 'foie'
True



"""
self.minet = minet
self.h=Hh()
for k,v in kwargs.items() :
setattr(self.h, k, v)

Ou, s'il y a également besoin d'un nombre d'arguments variables également
pour la classe Cla :

class Cla(object):
def __init__(self, **kwargs):
"""Named arguments beginning with 'h' will serve to initialize the
Hh owned by the instance, all others to initialize instance
members.
for example :
c = Cla(minet='chat', hfoie='foie')
c.h.foie == 'foie'
True



"""
self.h=hh()
for k,v in kwargs.items() :
if e.startswith('h')) :
setattr(self.h, k[1:], v)
else :
setattr(self, k, v)



_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097



Avatar
Méta-MCI
Bonjour !


Vous pouvez toujours écrire :
h=hh()
h.totoB
a=cla(titi='titi', h=h)


Autant utiliser directement :
a=cla(titi='titi')
a.h.totoB
Qui est plus simple et plus lisible. C'est ce que je fais dans mon
exemple_1. Mais, je cherchais à simplifier ça, pour ramener l'initialisation
en une (seule) ligne.



Il est préférable d'éviter les arguments variables


Désolé, mais j'ai besoin d'arguments variables. Certaines propriétés ne sont
pas connues à l'avance, et peuvent n'exister que selon l'installation (ça
dépend du matériel installé).

En l'occurrence, je n'utilise la classe "h" que comme un moyen de
"catégorier" (typer ?) les propriétés.



if e.startswith('h')) :


Ben, en pratique, j'avais opté pour une solution similaire :
startswith('h___')
C'est une solution que j'utilise depuis longtemps, car elle me permet de
régler un autre problème : certains langages d'origine refusent la notation
par point (ou par points multiples).
Ce qui revient à dire que je remplace, à la volée, le triple guillemet par
un point.

Mais, ce n'est pas très beau...



@-salutations, et merci d'avoir répondu à mon message.
--
Michel Claveau

Avatar
Bruno Desthuilliers
Re !

si par hasard tu n'écrase pas un attribut par accident


Oui, mais, là, je veux que ça écrase.


a = cla(titi='titi', h=h(totoB))


Ok, mais :
- je pense qu'il faudrait écrire a=cla(titi='titi', h=hh(totoB))


oops... Tout à fait, Thierry.

- c'est trop dur à lire, pour mon public ;


Alors il faut peut-être envisager une autre approche.