Chiamare una funzione di classe all'interno di __init__


132

Sto scrivendo del codice che accetta un nome file, apre il file ed analizza alcuni dati. Mi piacerebbe farlo in una classe. Il seguente codice funziona:

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()

Ma mi coinvolge mettendo tutti i macchinari di analisi nell'ambito della __init__funzione per la mia classe. Ora sembra a posto per questo codice semplificato, ma la funzione parse_fileha anche alcuni livelli di rientro. Preferirei definire la funzione parse_file()come una funzione di classe come di seguito:

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

Naturalmente questo codice non funziona perché la funzione parse_file()non rientra nell'ambito della __init__funzione. C'è un modo per chiamare una funzione di classe dall'interno __init__di quella classe? O sto pensando a questo nel modo sbagliato?


C'è qualche motivo per cui l'esempio di codice necessita di cinque versioni di "stat"? Sarebbe più facile da leggere se ce ne fosse solo uno.
465b

Risposte:


183

Chiamare la funzione in questo modo:

self.parse_file()

Devi anche definire la tua funzione parse_file () in questo modo:

def parse_file(self):

Il parse_filemetodo deve essere associato a un oggetto dopo averlo chiamato (perché non è un metodo statico). Questo viene fatto chiamando la funzione su un'istanza dell'oggetto, nel tuo caso l'istanza è self.


Sì! Questo era esattamente quello che stavo cercando. Grazie!
PythonJin,

33

Se non sbaglio, entrambe le funzioni fanno parte della tua classe, dovresti usarla in questo modo:

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

sostituisci la tua linea:

parse_file() 

con:

self.parse_file()

Potresti spiegare perché deve essere usato self.parse_file()e non parse_file()?
Ivanleoncz,

@paritoshsingh def parse_file(self):non dovrebbe essere nidificato sotto la __init__funzione in modo da non avere un oggetto parzialmente inizializzato?
donrondadon,

@ivanleoncz Poiché parse_file è il metodo di istanza, è necessario utilizzare l'oggetto di riferimento per chiamare lo stesso.
Paritosh Singh,

@rong Se questo codice è venerabile e non si desidera consentire l'impostazione del file di analisi dall'esterno, sì, dovrebbe essere nidificato.
Paritosh Singh,

12

Che ne dite di:

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

A proposito, se si dispone di variabili chiamate stat1, stat2e così via, la situazione è accattonaggio per una tupla: stats = (...).

Quindi lascia che parse_filerestituisca una tupla e riponila self.stats.

Quindi, per esempio, è possibile accedere a ciò che veniva chiamato stat3con self.stats[2].


Sono d'accordo, ho appena inserito self.stat1 attraverso self.stat5 per mostrare che c'erano alcune variabili di classe che stavo assegnando. Nel codice attuale ho una soluzione più elegante.
PythonJin,

Come dovrebbe essere modificato se voglio che la parse_filefunzione sia un metodo MyClassdell'oggetto. Dove sarebbe selfnecessario?
n1k31t4,

0

In parse_file, prendi l' selfargomento (proprio come in __init__). Se c'è qualche altro contesto di cui hai bisogno, passa semplicemente come argomenti aggiuntivi come al solito.


0

Devi dichiarare parse_file in questo modo; def parse_file(self). Il parametro "self" è un parametro nascosto nella maggior parte delle lingue, ma non in Python. È necessario aggiungerlo alla definizione di tutti quei metodi che appartengono a una classe. Quindi è possibile chiamare la funzione da qualsiasi metodo all'interno della classe utilizzandoself.parse_file

il tuo programma finale sarà simile al seguente:

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

-13

Penso che il tuo problema sia in realtà con la funzione init non rientrata correttamente. Dovrebbe essere così

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

     def parse_file():
          pass

Né è il tuo codice. A meno che tu non abbia messo il @staticmethoddecoratore sopra parse_file
rantanplan il

almeno aggiungi ciò che manca selfnel tuo parse_filemetodo.
rantanplan,

Spiacenti, ci sarebbe dovuto essere un ulteriore livello di rientro nella riga "class MyClass ():". L'ho risolto sopra, ma la domanda rimane la stessa.
PythonJin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.