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ę?


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.


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

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] .


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.


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

-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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.