Wywołanie funkcji klasy wewnątrz __init__

141

Piszę kod, który pobiera nazwę pliku, otwiera plik i analizuje niektóre dane. Chciałbym to zrobić w klasie. Poniższy kod działa:

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

Ale wymaga to umieszczenia całej maszyny parsującej w zakresie __init__funkcji dla mojej klasy. Teraz wygląda to dobrze w przypadku tego uproszczonego kodu, ale funkcja parse_filema również kilka poziomów wcięć. Wolałbym zdefiniować funkcję parse_file()jako funkcję klasową, jak poniżej:

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

Oczywiście ten kod nie działa, ponieważ funkcja parse_file()nie jest objęta zakresem __init__funkcji. Czy istnieje sposób wywołania funkcji klasy z poziomu __init__tej klasy? A może źle o tym myślę?

PythonJin
źródło
Czy jest jakiś powód, dla którego przykładowy kod wymaga pięciu wersji „stat”? Łatwiej byłoby czytać, gdyby był tylko jeden.
465b

Odpowiedzi:

197

Wywołaj funkcję w ten sposób:

self.parse_file()

Musisz także zdefiniować swoją funkcję parse_file () w następujący sposób:

def parse_file(self):

parse_fileMetoda musi być związany z obiektem na nazywając ją (bo to nie jest metoda statyczna). Odbywa się to poprzez wywołanie funkcji na instancji obiektu, w twoim przypadku jest to instancja self.

Lewis Diamond
źródło
Tak! To było dokładnie to, czego szukałem. Dziękuję Ci!
PythonJin
34

Jeśli się nie mylę, obie funkcje są częścią twojej klasy, powinieneś używać ich w następujący sposób:

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

zastąp linię:

parse_file() 

z:

self.parse_file()
Paritosh Singh
źródło
Czy mógłbyś wyjaśnić, dlaczego należy go używać, self.parse_file()a nie parse_file()?
ivanleoncz
@paritoshsingh def parse_file(self):nie powinno być zagnieżdżone w __init__funkcji, aby nie mieć częściowo zainicjowanego obiektu?
ron_g Kwietnia
@ivanleoncz Ponieważ parse_file jest metodą instancji, musimy użyć obiektu referencyjnego, aby wywołać to samo.
Paritosh Singh
@rong Jeśli ten kod jest szanowany i nie chcesz zezwalać na ustawianie pliku parsowania z zewnątrz, tak, powinien być zagnieżdżony.
Paritosh Singh
12

Co powiesz na:

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

Nawiasem mówiąc, jeśli masz zmienne o nazwach stat1, stat2itp, sytuacja jest żebranie na krotki: stats = (...) .

Zwróćmy więc parse_filekrotkę i zapiszmy ją w self.stats .

Następnie, na przykład, możesz uzyskać dostęp do tego, co było wywoływane za stat3pomocąself.stats[2] .

unutbu
źródło
Zgadzam się, po prostu wstawiłem tam od self.stat1 do self.stat5, aby pokazać, że istnieją pewne zmienne klasowe, do których przypisałem. W rzeczywistym kodzie mam bardziej eleganckie rozwiązanie.
PythonJin
Jak należy to zmienić, jeśli chcę, aby parse_filefunkcja była metodą MyClassobiektu. Gdzie byłoby selfto konieczne?
n1k31t4
0

W parse_file, weź selfargument (tak jak w __init__). Jeśli potrzebujesz innego kontekstu, po prostu przekaż go jako dodatkowe argumenty, jak zwykle.

Teo Klestrup Röijezon
źródło
0

Musisz zadeklarować parse_file w ten sposób; def parse_file(self). Parametr „self” jest ukrytym parametrem w większości języków, ale nie w Pythonie. Musisz dodać go do definicji wszystkich metod należących do klasy. Następnie możesz wywołać funkcję z dowolnej metody wewnątrz klasy za pomocąself.parse_file

Twój ostateczny program będzie wyglądał następująco:

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
źródło
-14

Myślę, że twój problem w rzeczywistości polega na nieprawidłowym wcięciu funkcji init. Powinno być tak

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

     def parse_file():
          pass
Zed
źródło
Twój kod też nie. Chyba że umieścisz @staticmethoddekoratora na wierzchu parse_file
rantanplan
przynajmniej dodaj brakujące selfw swojej parse_filemetodzie.
rantanplan
Ups, przepraszam, że powinna istnieć dodatkowa warstwa wcięć pod linią "class MyClass ():". Poprawiłem to powyżej, ale pytanie pozostaje takie samo.
PythonJin