Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Appeler une méthode d'une classe A depuis une classe B

+4 votes

J'ai une classe A qui a deux méthodes qui m'intéressent; m1 et m2.
J'ai une classe B qui a comme attribut une liste d'objets de classe A.

Je souhaite faire une méthode de B qui puisse prendre comme argument m1 ou m2.

Le code suivant explicite mon problème :

class A:

    def __init__(self):
        self.param=1
    def m1(self,N):
        self.param=N
    def m2(self,N):
        self.param=2*N


class B:

    def __init__(self,M):
        self.liste=[A() for i in range(M)]
        self.long=M

    def fonction_pb(self,fonction_a_utiliser,chiffre):
        self.liste=[self.liste[i].fonction_a_utiliser(chiffre) for i in range(self.long)]


mon_B=B(10)
mon_B.fonction_pb(A.m1,3) 

L'exécution de ce code renvoie un : "A instance has no attribute 'fonctionautiliser'"

Comment faire pour pouvoir utiliser au choix A.m1 ou A.m2 dans une fonction de B ?

demandé 16-Mar-2015 par Beoti1 (156 points)

2 Réponses

+4 votes
 
Meilleure réponse
def fonction_pb(self, fonction_a_utiliser, chiffre):
    for a in self.liste:
        fonction_a_utiliser(a, chiffre)

vu ton exemple, ceci devrait faire ce que tu veux.

répondu 16-Mar-2015 par bubulle (2,256 points)
sélectionné 16-Mar-2015 par Beoti1

carrément mieux!!!
l'argument self de la méthode A.m1 prend ici tout son sens!

Merci à vous deux.
C'est exactement ce que je souhaitais.

+1 vote

ci dessous un code qui marche!

class A(object):
    def __init__(self):
        self.param=1
    def __repr__(self):
        return "(A:{})".format(self.param)
    def m1(self,N):
        self.param=N
    def m2(self,N):
        self.param=2*N


class B(object):
    def __init__(self,M):
        self.liste=[A() for i in range(M)]
        print(self.liste)
        self.long=M

    def fonction_pb(self,fonction_a_utiliser,chiffre):
        nom_fonction_a_utiliser = fonction_a_utiliser.__name__
        for a in self.liste:
            a.__getattribute__(nom_fonction_a_utiliser)(chiffre)
        print(self.liste)


mon_B=B(10)
mon_B.fonction_pb(A.m1,3)

sorties :

>>>python attr.py 
[(A:1), (A:1), (A:1), (A:1), (A:1), (A:1), (A:1), (A:1), (A:1), (A:1)]
[(A:3), (A:3), (A:3), (A:3), (A:3), (A:3), (A:3), (A:3), (A:3), (A:3)]

quelques commentaires :

  • il te faut utiliser la méthode __getattr__, définie dans les classes dépendant de object, avec comme paramètre le nom de la méthode à utiliser (en string)

  • une méthode/fonction est un objet python qui a elle aussi des méthodes et attributs. L'attribut __name__ te revoit le nom de la méthode, et permet ici de garder A.m1 comme argument pour fonction_pb. Évidement A.m1.__name__ == "m1"

  • une erreur dans ton code, dans sa construction : dans la méthode fonction_pb, quand tu redéfinis self.liste

    def fonction_pb(self,fonction_a_utiliser,chiffre):
        self.liste=[self.liste[i].fonction_a_utiliser(chiffre) for i in range(self.long)]
    

    ta nouvelle liste collecte les retours de l'appel à la méthode (m1 ici), qui ne sont pas définie, et donc tu auras une liste de None. Ma redéfinition n'est peut être pas la plus pythonesque, mais marche bien (en fait, tu n'as pas besoin de redéfinir la liste, juste de changer des valeurs propres aux éléments qu'elle contient)

  • j'ai ajouté une méthode __repr__ à A, qui permet d'avoir une sortie plus sympa pour débugger...

répondu 16-Mar-2015 par Lhassa (798 points)
edité 16-Mar-2015 par Lhassa

au vue de la réponse de bubulle, la mienne est capillotractée...

...