Chamando uma função de classe dentro de __init__

132

Estou escrevendo um código que pega um nome de arquivo, abre o arquivo e analisa alguns dados. Eu gostaria de fazer isso em uma aula. O código a seguir funciona:

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

Mas isso envolve colocar todo o mecanismo de análise no escopo da __init__função da minha classe. Parece bom agora para esse código simplificado, mas a função também parse_filepossui alguns níveis de indentação. Eu preferiria definir a função parse_file()como uma função de classe como abaixo:

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

É claro que esse código não funciona porque a função parse_file()não está dentro do escopo da __init__função. Existe uma maneira de chamar uma função de classe de dentro __init__dessa classe? Ou estou pensando nisso da maneira errada?

PythonJin
fonte
Existe alguma razão para o exemplo de código precisar de cinco versões de "stat"? Seria mais fácil ler se houvesse apenas um.
465b 29/04

Respostas:

183

Chame a função desta maneira:

self.parse_file()

Você também precisa definir sua função parse_file () assim:

def parse_file(self):

O parse_filemétodo deve ser vinculado a um objeto ao chamá-lo (porque não é um método estático). Isso é feito chamando a função em uma instância do objeto, no seu caso a instância é self.

Lewis Diamond
fonte
Sim! Era exatamente isso que eu estava procurando. Obrigado!
precisa saber é o seguinte
33

Se não estou errado, ambas as funções fazem parte da sua classe, você deve usá-lo assim:

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

substitua sua linha:

parse_file() 

com:

self.parse_file()
Paritosh Singh
fonte
Você poderia explicar por que ele deve ser usado self.parse_file()e não parse_file()?
precisa saber é o seguinte
@paritoshsingh def parse_file(self):não deve ser aninhado sob a __init__função para que você não tenha um objeto parcialmente inicializado?
donrondadon
@ivanleoncz Como parse_file é um método de instância, precisamos usar o objeto de referência para chamá-lo.
Paritosh Singh
@rong Se esse código é venerável e você não deseja permitir a configuração de um arquivo de análise de fora, sim, ele deve ser aninhado.
Paritosh Singh
12

E se:

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

By the way, se você tem variáveis nomeadas stat1, stat2etc., a situação está implorando por uma tupla: stats = (...).

Portanto, vamos parse_fileretornar uma tupla e armazenar a tupla self.stats.

Então, por exemplo, você pode acessar o que costumava ser chamado stat3com self.stats[2].

unutbu
fonte
Concordo, apenas coloquei o self.stat1 no self.stat5 para mostrar que havia algumas variáveis ​​de classe às quais eu estava atribuindo. No código atual, tenho uma solução mais elegante.
precisa saber é o seguinte
Como isso deve ser alterado se eu quiser que a parse_filefunção seja um método do MyClassobjeto. Onde seria selfnecessário?
N1k31t4 01/07/19
0

Em parse_file, aceite o selfargumento (assim como em __init__). Se houver qualquer outro contexto necessário, basta transmiti-lo como argumentos adicionais, como de costume.

Teo Klestrup Röijezon
fonte
0

Você deve declarar parse_file assim; def parse_file(self). O parâmetro "self" é um parâmetro oculto na maioria dos idiomas, mas não no python. Você deve adicioná-lo à definição de todos os métodos que pertencem a uma classe. Em seguida, você pode chamar a função de qualquer método dentro da classe usandoself.parse_file

seu programa final ficará assim:

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
fonte
-13

Eu acho que o seu problema é realmente não recuar corretamente a função init . Deve ser assim

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

     def parse_file():
          pass
Zed
fonte
O seu código também não é. A menos que você coloque o @staticmethoddecorador em cima de parse_file
rantanplan
pelo menos adicione a falta selfno seu parse_filemétodo.
Rantanplan
Ops, desculpe, deveria ter havido uma camada extra de recuo na linha "class MyClass ():". Corrigi-o acima, mas a questão permanece a mesma.
precisa saber é o seguinte