OVH Cloud OVH Cloud

appel d'une méthode avec une chaine

5 réponses
Avatar
Jonathan Barnoud
Bonjour

C'est les vacances et j'essaie de programmer un jeu en réseau.


J'aimerais que mes client s'envoient des chaines du style : "METHODE objet
param1,param2" et que cela puisse amener les autres clients à appeller quelque chose
du genre :
items["objet"].METHODE(param1, param2)

sachant bien sur que l'objet items["objet"] existe et a une méthode METHODE qui prend
param1 et param2 comme paramètre mais que la requête à la base ("METHODE objet
param1,param2") est une chaine.

Question auxiliaure : est-il possible pour ma méthode METHODE de modifier self.param1
par exemple ? ou dois-je obligatoirement passer par un dictionnaire ?

Bien sur, si vous avez une idée sur une autre façon de faire je suis preneur
(parceque là je patauge un peu...)

Jonathan Barnoud (qui espère être compréhensible et même mieu compri...)

5 réponses

Avatar
tiissa
Jonathan Barnoud wrote:
J'aimerais que mes client s'envoient des chaines du style : "METHODE
objet param1,param2" et que cela puisse amener les autres clients à
appeller quelque chose du genre :
items["objet"].METHODE(param1, param2)


J'essaierais peut-être de parser le message et d'utiliser getattr :

########
def appelle_vite(message):
methode, objet, params = message.split(' ')
args = params.split(',')
getattr(objets[objet], methode)(*args)
########

ou en faisant plus gaffe aux erreurs potentielles :

########
def appelle(message):
try:
methode, objet, params = message.split(' ')
except ValueError:
print 'Message "%s" incorrect.'%message
return
args = params.split(',')
try:
getattr(objets[objet], methode)(*args)
except KeyError:
print 'Objet %s inconnu.'%objet
except AttributeError:
print 'Methode %s inconnue.'%methode
except TypeError:
print 'Argument(s) incorrect(s).'
########

On peut tester avec :

########
class A(object):
def __init__(self, nom):
self.nom = nom
def m1(self, *args):
print 'm1 de %s appele avec : '%self.nom + ', '.join(args)
def m2(self, p1, p2):
print 'm2 de %s appele avec p1=%s et p2=%s.'%(self.nom, p1, p2)

a1 = A('a1')
a2 = A('a2')
objets = {'a1': a1, 'a2': a2}

appelle('m2 a1 a,b')
appelle('m2 a2 a,b')
appelle('m1 a1 ') # pas d'argument
appelle('m1 a3 ') # l'objet n'existe pas
appelle('m3 a1 ') # la methode n'existe pas
appelle('m1 a1') # le split va echouer
appelle('m2 a1 1') # pas assez d'arguments
appelle('m1 a1 1,2 , 0.1') # le premier split va echouer
########

Ca donne :

m2 de a1 appele avec p1=a et p2=b.
m2 de a2 appele avec p1=a et p2=b.
m1 de a1 appele avec :
Objet a3 inconnu.
Methode m3 inconnue.
Message "m1 a1" incorrect.
Argument(s) incorrect(s).
Message "m1 a1 1,2 , 0.1" incorrect.


Voila. C'est encore loin d'être parfait, en particulier du côté de
l'analyse du message (il faut faire attention aux arguments par exemple)
mais peut-être que ça vous aidera.


Question auxiliaure : est-il possible pour ma méthode METHODE de
modifier self.param1 par exemple ?


Oui. Modifier des membres d'un objet est une des choses courantes faites
dans ses méthodes.

Mais la question porte peut-être sur param1 (au lieu de self.param1)
auquel cas la réponse générale est oui (en utilisant les méthodes de
param1 qui le permettent s'il y en a).

Ou alors je suis passé à côté de la question (mais certains ne sont pas
en vacances et ont l'excuse d'être fatigués après une journée de travail
;)).

Avatar
Jonathan Barnoud
Jonathan Barnoud wrote:

J'aimerais que mes client s'envoient des chaines du style : "METHODE
objet param1,param2" et que cela puisse amener les autres clients à
appeller quelque chose du genre :
items["objet"].METHODE(param1, param2)



J'essaierais peut-être de parser le message et d'utiliser getattr :

########
def appelle_vite(message):
methode, objet, params = message.split(' ')
args = params.split(',')
getattr(objets[objet], methode)(*args)
########

ou en faisant plus gaffe aux erreurs potentielles :

########
def appelle(message):
try:
methode, objet, params = message.split(' ')
except ValueError:
print 'Message "%s" incorrect.'%message
return
args = params.split(',')
try:
getattr(objets[objet], methode)(*args)
except KeyError:
print 'Objet %s inconnu.'%objet
except AttributeError:
print 'Methode %s inconnue.'%methode
except TypeError:
print 'Argument(s) incorrect(s).'
########

On peut tester avec :

########
class A(object):
def __init__(self, nom):
self.nom = nom
def m1(self, *args):
print 'm1 de %s appele avec : '%self.nom + ', '.join(args)
def m2(self, p1, p2):
print 'm2 de %s appele avec p1=%s et p2=%s.'%(self.nom, p1, p2)

a1 = A('a1')
a2 = A('a2')
objets = {'a1': a1, 'a2': a2}

appelle('m2 a1 a,b')
appelle('m2 a2 a,b')
appelle('m1 a1 ') # pas d'argument
appelle('m1 a3 ') # l'objet n'existe pas
appelle('m3 a1 ') # la methode n'existe pas
appelle('m1 a1') # le split va echouer
appelle('m2 a1 1') # pas assez d'arguments
appelle('m1 a1 1,2 , 0.1') # le premier split va echouer
########

Ca donne :

m2 de a1 appele avec p1=a et p2=b.
m2 de a2 appele avec p1=a et p2=b.
m1 de a1 appele avec :
Objet a3 inconnu.
Methode m3 inconnue.
Message "m1 a1" incorrect.
Argument(s) incorrect(s).
Message "m1 a1 1,2 , 0.1" incorrect.


Voila. C'est encore loin d'être parfait, en particulier du côté de
l'analyse du message (il faut faire attention aux arguments par exemple)
mais peut-être que ça vous aidera.


Merci, c'et exactement ça que je cherchais. Je vais pouvoir avancé maintenant.


Question auxiliaure : est-il possible pour ma méthode METHODE de
modifier self.param1 par exemple ?



Oui. Modifier des membres d'un objet est une des choses courantes faites
dans ses méthodes.

Mais la question porte peut-être sur param1 (au lieu de self.param1)
auquel cas la réponse générale est oui (en utilisant les méthodes de
param1 qui le permettent s'il y en a).

Ou alors je suis passé à côté de la question (mais certains ne sont pas
en vacances et ont l'excuse d'être fatigués après une journée de travail
;)).


L'idée aurait été de pouvoir faire quelque chose du genre :

class Test:
def __init__(self):
self.test = "test"
self.getattr("test") = "test2"

toto = Test() #qui afficherait "test2"

En effet, j'ai une méthode qui modifie l'une des caractéristique de mon personnage,
elle prend le nom de la caractéristique et la modification en paramètre.

def alter(key, val):
try :
self.vals[key] += int(val)
except KeyError :
print "La clé %s n'esiste pas." % key

et j'aurais voulu utiliser self.key plutôt que self.vals["key"].

Jonathan Barnoud


Avatar
Jonathan Barnoud

Jonathan Barnoud wrote:

[snip]


Merci, c'et exactement ça que je cherchais. Je vais pouvoir avancé
maintenant.

[snap]


Jonathan Barnoud


Merci c'eSt exactement ce que je cherchais. Je vais pouvoir avancER maintenant.

Raaa ces jeunes ! Ils savent même plus écrire !!

Jonathan Barnoud


Avatar
tiissa
class Test:
def __init__(self):
self.test = "test"
self.getattr("test") = "test2"

toto = Test() #qui afficherait "test2"


Attention, getattr n'est pas /a priori/ une methode de ta classe ; il
s'agit d'un builtin [1]. De plus il renvoie la valeur (l'objet) donc il
ne se modifie pas ainsi.
Ton affectation s'ecrirait plutot (en plus de self.test = 'test2'):
setattr(self, 'test', 'test2')

En effet, j'ai une méthode qui modifie l'une des caractéristique de m on personnage,
elle prend le nom de la caractéristique et la modification en paramèt re.

def alter(key, val):
try :
self.vals[key] += int(val)
except KeyError :
print "La clé %s n'esiste pas." % key

et j'aurais voulu utiliser self.key plutôt que self.vals["key"].


Le probleme de self.key est qu'il cherche un membre de nom 'key'. Il
faudrait lui dire que le nom est key et non pas 'key'. C'est le but des
(get|set|del)attr.

Par contre, tu peux aussi utiliser le dictionnaire des membres d'un
objet : __dict__ [2] plutot que d'en creer un autre.

Si tu veux pouvoir utiliser a.test et a.alter('test', val), tu peux
alors ecrire au choix (sans oublier de passer self a alter ;)) :

########
class A(object):
def alter(self, key, val):
try:
setattr(self, key, getattr(self, key) + val)
except AttributeError:
print "La cle %s n'existe pas"%key
def alter2(self, key, val):
try:
self.__dict__[key] += val
except KeyError:
print "La cle %s n'existe pas"%key
########

A l'utilisation on a bien :

a=A()
a.test=0
a.test
0



a.alter('test', 1)
a.alter2('test', 1)
a.test
2



a.alter('test2', 1)
La cle test2 n'existe pas



a.alter2('test2', 1)
La cle test2 n'existe pas





Voila, j'espere que j'ai bien compris le probleme. :)


[1] http://docs.python.org/lib/built-in-funcs.html
[2] http://docs.python.org/lib/specialattrs.html



Avatar
Jonathan Barnoud

class Test:
def __init__(self):
self.test = "test"
self.getattr("test") = "test2"

toto = Test() #qui afficherait "test2"



Attention, getattr n'est pas /a priori/ une methode de ta classe ; il
s'agit d'un builtin [1]. De plus il renvoie la valeur (l'objet) donc il
ne se modifie pas ainsi.
Ton affectation s'ecrirait plutot (en plus de self.test = 'test2'):
setattr(self, 'test', 'test2')


En effet, j'ai une méthode qui modifie l'une des caractéristique de mon personnage,
elle prend le nom de la caractéristique et la modification en paramètre.

def alter(key, val):
try :
self.vals[key] += int(val)
except KeyError :
print "La clé %s n'esiste pas." % key

et j'aurais voulu utiliser self.key plutôt que self.vals["key"].



Le probleme de self.key est qu'il cherche un membre de nom 'key'. Il
faudrait lui dire que le nom est key et non pas 'key'. C'est le but des
(get|set|del)attr.

Par contre, tu peux aussi utiliser le dictionnaire des membres d'un
objet : __dict__ [2] plutot que d'en creer un autre.

Si tu veux pouvoir utiliser a.test et a.alter('test', val), tu peux
alors ecrire au choix (sans oublier de passer self a alter ;)) :

########
class A(object):
def alter(self, key, val):
try:
setattr(self, key, getattr(self, key) + val)
except AttributeError:
print "La cle %s n'existe pas"%key
def alter2(self, key, val):
try:
self.__dict__[key] += val
except KeyError:
print "La cle %s n'existe pas"%key
########

A l'utilisation on a bien :


a=A()
a.test=0
a.test




0

a.alter('test', 1)
a.alter2('test', 1)
a.test




2

a.alter('test2', 1)




La cle test2 n'existe pas

a.alter2('test2', 1)




La cle test2 n'existe pas


Voila, j'espere que j'ai bien compris le probleme. :)


[1] http://docs.python.org/lib/built-in-funcs.html
[2] http://docs.python.org/lib/specialattrs.html



Merci beaucoup. Je vais pouvoir faire de beaux objets maintenant plutôt que les trucs
bancaux que je faisait jusqu'à présent.
Et puis il va faloir que je prennent le temps d'apprendre à lire avant de poser ma
prochaine question :)

Jonathan Barnoud