Appel d'une fonction de classe à l'intérieur de __init__

132

J'écris du code qui prend un nom de fichier, ouvre le fichier et analyse certaines données. J'aimerais faire ça en classe. Le code suivant fonctionne:

class MyClass():
    def __init__(self, filename):
        self.filename = filename 

        self.stat1 = None
        self.stat2 = None
        self.stat3 = None
        self.stat4 = None
        self.stat5 = None

        def parse_file():
            #do some parsing
            self.stat1 = result_from_parse1
            self.stat2 = result_from_parse2
            self.stat3 = result_from_parse3
            self.stat4 = result_from_parse4
            self.stat5 = result_from_parse5

        parse_file()

Mais cela m'implique de mettre toutes les machines d'analyse dans le cadre de la __init__fonction de ma classe. Cela semble bien maintenant pour ce code simplifié, mais la fonction parse_filea également plusieurs niveaux d'indention. Je préfère définir la fonction parse_file()comme une fonction de classe comme ci-dessous:

class MyClass():
    def __init__(self, filename):
        self.filename = filename 

        self.stat1 = None
        self.stat2 = None
        self.stat3 = None
        self.stat4 = None
        self.stat5 = None
        parse_file()

    def parse_file():
        #do some parsing
        self.stat1 = result_from_parse1
        self.stat2 = result_from_parse2
        self.stat3 = result_from_parse3
        self.stat4 = result_from_parse4
        self.stat5 = result_from_parse5

Bien sûr, ce code ne fonctionne pas car la fonction parse_file()n'est pas dans le cadre de la __init__fonction. Existe-t-il un moyen d'appeler une fonction de classe à partir __init__de cette classe? Ou est-ce que je pense à cela de la mauvaise façon?

PythonJin
la source
Y a-t-il une raison pour laquelle l'exemple de code nécessite cinq versions de "stat"? Ce serait plus facile à lire s'il n'y en avait qu'un.
465b le

Réponses:

184

Appelez la fonction de cette manière:

self.parse_file()

Vous devez également définir votre fonction parse_file () comme ceci:

def parse_file(self):

La parse_fileméthode doit être liée à un objet lors de son appel (car ce n'est pas une méthode statique). Cela se fait en appelant la fonction sur une instance de l'objet, dans votre cas l'instance est self.

Lewis Diamond
la source
Oui! C'était exactement ce que je cherchais. Je vous remercie!
PythonJin du
33

Si je ne me trompe pas, les deux fonctions font partie de votre classe, vous devriez l'utiliser comme ceci:

class MyClass():
    def __init__(self, filename):
        self.filename = filename 

        self.stat1 = None
        self.stat2 = None
        self.stat3 = None
        self.stat4 = None
        self.stat5 = None
        self.parse_file()

    def parse_file(self):
        #do some parsing
        self.stat1 = result_from_parse1
        self.stat2 = result_from_parse2
        self.stat3 = result_from_parse3
        self.stat4 = result_from_parse4
        self.stat5 = result_from_parse5

remplacez votre ligne:

parse_file() 

avec:

self.parse_file()
Paritosh Singh
la source
Pourriez-vous expliquer pourquoi il doit être utilisé self.parse_file()et non parse_file()?
ivanleoncz
@paritoshsingh def parse_file(self):ne doit pas être imbriqué sous la __init__fonction pour ne pas avoir d'objet partiellement initialisé?
donrondadon
@ivanleoncz Comme parse_file est une méthode d'instance, nous devons utiliser un objet de référence pour l'appeler.
Paritosh Singh
@rong Si ce code est vénérable et que vous ne voulez pas autoriser la configuration du fichier d'analyse de l'extérieur, oui, il devrait être imbriqué.
Paritosh Singh
12

Que diriez-vous:

class MyClass(object):
    def __init__(self, filename):
        self.filename = filename 
        self.stats = parse_file(filename)

def parse_file(filename):
    #do some parsing
    return results_from_parse

Soit dit en passant, si vous avez des variables nommées stat1, stat2etc., la situation est la mendicité pour un tuple: stats = (...).

Alors, parse_fileretournons un tuple et stockons le tuple dans self.stats.

Ensuite, par exemple, vous pouvez accéder à ce qui était appelé stat3avec self.stats[2].

unutbu
la source
Je suis d'accord, je viens de mettre self.stat1 à self.stat5 pour montrer qu'il y avait des variables de classe auxquelles j'attribuais. Dans le code actuel, j'ai une solution plus élégante.
PythonJin du
Comment cela devrait-il être modifié si je veux que la parse_filefonction soit une méthode de l' MyClassobjet. Où serait- selfil nécessaire?
n1k31t4
0

Dans parse_file, prenez l' selfargument (comme dans __init__). S'il y a un autre contexte dont vous avez besoin, transmettez-le simplement comme arguments supplémentaires, comme d'habitude.

Teo Klestrup Röijezon
la source
0

Vous devez déclarer parse_file comme ceci; def parse_file(self). Le paramètre "self" est un paramètre caché dans la plupart des langages, mais pas en python. Vous devez l'ajouter à la définition de toutes les méthodes qui appartiennent à une classe. Ensuite, vous pouvez appeler la fonction à partir de n'importe quelle méthode à l'intérieur de la classe en utilisantself.parse_file

votre programme final ressemblera à ceci:

class MyClass():
  def __init__(self, filename):
      self.filename = filename 

      self.stat1 = None
      self.stat2 = None
      self.stat3 = None
      self.stat4 = None
      self.stat5 = None
      self.parse_file()

  def parse_file(self):
      #do some parsing
      self.stat1 = result_from_parse1
      self.stat2 = result_from_parse2
      self.stat3 = result_from_parse3
      self.stat4 = result_from_parse4
      self.stat5 = result_from_parse5
Ionut Hulub
la source
-13

Je pense que votre problème est en fait de ne pas indenter correctement la fonction init . Cela devrait être comme ça

class MyClass():
     def __init__(self, filename):
          pass

     def parse_file():
          pass
Zed
la source
Votre code non plus. Sauf si vous mettez le @staticmethoddécorateur au-dessus de parse_file
rantanplan
ajoutez au moins les éléments manquants selfdans votre parse_fileméthode.
rantanplan
Oups, désolé, il aurait dû y avoir une couche supplémentaire d'indentation sous la ligne "class MyClass ():". Je l'ai corrigé ci-dessus, mais la question reste la même.
PythonJin du