71 votes

L'appel d'une méthode de classe soulève une TypeError en 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 qu'il y a ?

5 votes

Considérez les classes comme le moule. Vous n'interagissez pas réellement avec le moule lui-même, mais vous utilisez le moule pour créer des objets avec lesquels vous pouvez ensuite interagir. Pour faire quelque chose avec l'objet, vous devez d'abord le créer.

88voto

Ryan Points 385

Vous pouvez instancier la classe en déclarant une variable et en appelant la classe 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 comme premier paramètre lorsqu'elle 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 devez modifier la définition de la méthode average pour qu'elle prenne quatre paramètres. Le premier paramètre est une référence d'objet, et les 3 autres paramètres seraient pour les 3 nombres.

0 votes

Vous voulez dire qu'il devrait prendre l'argument lui-même ?

8 votes

Vous pouvez l'appeler comme vous voulez. "self" est juste une convention.

11 votes

@JoshSmeaton Vous devriez vraiment utiliser "self", car même si ce n'est pas techniquement nécessaire, c'est une convention très standard et cela rendrait votre code plus courant pour les autres développeurs python.

34voto

Roberto Liffredo Points 15265

D'après votre exemple, il me semble que vous voulez 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'un usage intensif des méthodes statiques en 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.

2 votes

Désolé pour le vote négatif, mais je pense que vous avez mal interprété la question. Il semble que Stu soit novice en Python, donc l'orienter vers de bonnes ressources sur les bases de Python est probablement mieux que de lui montrer comment utiliser les méthodes statiques ;)

9 votes

D'un autre côté, l'utilisation explicite de "self" en python et les croyances erronées sur les méthodes statiques sont un piège assez commun pour les personnes venant d'autres langages. Comme beaucoup d'entre nous indiquent de la documentation et des ressources, je pense qu'il devrait y avoir au moins une réponse "directe". Merci pour le commentaire !

1 votes

À moins que vous ne fassiez une classe utilitaire, ce qui permet de créer beaucoup de méthodes statiques et de classes.

13voto

cmoman Points 21

Pour modifier au minimum votre exemple, vous pourriez modifier le code comme suit :

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 de l'étendre plus complètement, en 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()

0 votes

Est-ce que cela va si nous faisons simplement myclass().average(a,b,c) ?

1 votes

@DJ_Stuffy_K ce code fonctionne pour mon premier exemple de code. Mais la question originale concernait l'instanciation de la classe, j'ai donc inclus la méthode def __init__(). Votre extrait de code instancie la classe mais il n'y a pas de "poignée" permettant d'accéder à d'autres méthodes qui pourraient utiliser les mêmes variables d'instance. Cela peut peut-être vous aider.

4voto

lmount Points 384

Chaque fonction à l'intérieur d'une classe, et chaque variable de classe doit prendre l'option self argument 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

1voto

Suraj Barkale Points 1482

En python, les fonctions membres d'une classe doivent être explicites. self argument. Identique à l'implicite this pointeur en C++. Pour plus de détails, veuillez consulter este page.

3 votes

Pas d'accord. Ce qui n'est pas obligatoire, c'est le nom du "moi". Mais le premier argument d'une fonction membre Python est une référence à un objet. Bien sûr, vous avez des méthodes de classe et des méthodes statiques, mais pour les méthodes d'instance, la règle s'applique.

1 votes

@Abgan : en fait, cela s'applique même aux méthodes de classe et statiques -- les décorateurs font juste un peu d'automangling pour que la fonction enveloppée reçoive des paramètres différents de ceux de l'enveloppe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X