web-dev-qa-db-fra.com

L'appel d'une méthode de classe déclenche une TypeError dans Python

Je ne comprends pas comment les classes sont utilisées. Le code suivant me donne une erreur lorsque j'essaie d'utiliser la classe.

class MyStuff:
    def average(a, b, c): # Get the average of three numbers
        result = a + b + c
        result = result / 3
        return result

# Now use the function `average` from the `MyStuff` class
print(MyStuff.average(9, 18, 27))

Erreur:

File "class.py", line 7, in <module>
    print(MyStuff.average(9, 18, 27))
TypeError: unbound method average() must be called with MyStuff instance as first argument (got int instance instead)

Qu'est-ce qui ne va pas?

71
stu

Vous pouvez instancier la classe en déclarant une variable et en l'appelant comme s'il s'agissait d'une fonction:

x = mystuff()
print x.average(9,18,27)

Cependant, cela ne fonctionnera pas avec le code que vous nous avez donné. Lorsque vous appelez une méthode de classe sur un objet donné (x), elle passe toujours un pointeur sur l'objet en tant que premier paramètre lorsqu'il appelle la fonction. Donc, si vous exécutez votre code maintenant, vous verrez ce message d'erreur:

TypeError: average() takes exactly 3 arguments (4 given)

Pour résoudre ce problème, vous devrez modifier la définition de la méthode moyenne afin de prendre quatre paramètres. Le premier paramètre est une référence d'objet, et les 3 paramètres restants seraient pour les 3 nombres.

87
Ryan

D'après votre exemple, il me semble que vous souhaitez utiliser une méthode statique.

class mystuff:
  @staticmethod
  def average(a,b,c): #get the average of three numbers
    result=a+b+c
    result=result/3
    return result

print mystuff.average(9,18,27)

Veuillez noter qu'une utilisation intensive de méthodes statiques dans python est généralement le symptôme d'une mauvaise odeur - si vous avez vraiment besoin de fonctions, déclarez-les directement au niveau du module.

34
rob

Pour modifier votre exemple de manière minimale, vous pouvez modifier le code en:

class myclass(object):
        def __init__(self): # this method creates the class object.
                pass

        def average(self,a,b,c): #get the average of three numbers
                result=a+b+c
                result=result/3
                return result


mystuff=myclass()  # by default the __init__ method is then called.      
print mystuff.average(a,b,c)

Ou pour le développer plus complètement, vous permettant d'ajouter d'autres méthodes.

class myclass(object):
        def __init__(self,a,b,c):
                self.a=a
                self.b=b
                self.c=c
        def average(self): #get the average of three numbers
                result=self.a+self.b+self.c
                result=result/3
                return result

a=9
b=18
c=27
mystuff=myclass(a, b, c)        
print mystuff.average()
13
cmoman

Chaque fonction dans une classe et chaque variable de classe doivent prendre l'argument self comme indiqué.

class mystuff:
    def average(a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result
    def sum(self,a,b):
            return a+b


print mystuff.average(9,18,27) # should raise error
print mystuff.sum(18,27) # should be ok

Si des variables de classe sont impliquées:

 class mystuff:
    def setVariables(self,a,b):
            self.x = a
            self.y = b
            return a+b
    def mult(self):
            return x * y  # This line will raise an error
    def sum(self):
            return self.x + self.y

 print mystuff.setVariables(9,18) # Setting mystuff.x and mystuff.y
 print mystuff.mult() # should raise error
 print mystuff.sum()  # should be ok
4
lmount

Essaye ça:

class mystuff:
    def average(_,a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result

#now use the function average from the mystuff class
print mystuff.average(9,18,27)

ou ca:

class mystuff:
    def average(self,a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result

#now use the function average from the mystuff class
print mystuff.average(9,18,27)
1
Rob123

Dans python, la fonction membre d'une classe nécessite l'argument explicite self. Identique au pointeur implicite this en C++. Pour plus de détails, consultez this page.

1
Suraj

Vous devez passer un peu plus de temps sur quelques notions de base de la programmation orientée objet.

Cela semble dur, mais c'est important.

  • Votre définition de classe est incorrecte - bien que la syntaxe soit acceptable. La définition est tout simplement fausse.

  • Votre utilisation de la classe pour créer un objet est entièrement manquante.

  • Votre utilisation d'une classe pour effectuer un calcul est inappropriée. Ce genre de chose peut être fait, mais cela nécessite le concept avancé d'un @staticmehod.

Étant donné que votre exemple de code est erroné à bien des égards, vous ne pouvez pas obtenir une réponse claire "réparer cela". Il y a trop de choses à réparer.

Vous devrez examiner de meilleurs exemples de définitions de classe. Le contenu des sources que vous utilisez pour apprendre n'est pas clair, mais le livre que vous lisez est faux ou incomplet.

Veuillez supprimer le livre ou la source que vous utilisez et trouver un meilleur livre. Sérieusement. Ils vous ont induit en erreur sur l'apparence d'une définition de classe et sur son utilisation.

Vous voudrez peut-être consulter http://homepage.mac.com/s_lott/books/nonprog/htmlchunks/pt11.html pour une meilleure introduction aux classes, aux objets et à Python.

1
S.Lott