Llamar a una función de clase dentro de __init__

132

Estoy escribiendo un código que toma un nombre de archivo, abre el archivo y analiza algunos datos. Me gustaría hacer esto en una clase. El siguiente código 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()

Pero me involucra poner toda la maquinaria de análisis en el alcance de la __init__función para mi clase. Ahora se ve bien para este código simplificado, pero la función también parse_filetiene bastantes niveles de sangría. Prefiero definir la función parse_file()como una función de clase como a continuación:

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

Por supuesto, este código no funciona porque la función parse_file()no está dentro del alcance de la __init__función. ¿Hay alguna manera de llamar a una función de clase desde dentro __init__de esa clase? ¿O estoy pensando en esto de la manera incorrecta?

PythonJin
fuente
¿Hay alguna razón para que el ejemplo de código necesite cinco versiones de "stat"? Sería más fácil de leer si hubiera solo uno.
465b

Respuestas:

183

Llame a la función de esta manera:

self.parse_file()

También necesita definir su función parse_file () de esta manera:

def parse_file(self):

El parse_filemétodo tiene que estar vinculado a un objeto al llamarlo (porque no es un método estático). Esto se hace llamando a la función en una instancia del objeto, en su caso la instancia es self.

Lewis Diamond
fuente
¡Si! Esto era exactamente lo que estaba buscando. ¡Gracias!
PythonJin
33

Si no me equivoco, ambas funciones son parte de tu clase, deberías usarla así:

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

reemplace su línea:

parse_file() 

con:

self.parse_file()
Paritosh Singh
fuente
¿Podría explicar por qué debe usarse self.parse_file()y no parse_file()?
ivanleoncz
@paritoshsingh def parse_file(self):no debe estar anidado bajo la __init__función para que no tenga un objeto parcialmente inicializado?
donrondadon
@ivanleoncz Como parse_file es un método de instancia, necesitamos usar el objeto de referencia para llamarlo.
Paritosh Singh
@rong Si este código es venerable y no desea permitir la configuración del archivo de análisis desde el exterior, sí, debe estar anidado.
Paritosh Singh
12

Qué tal si:

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

Por cierto, si usted tiene variables con nombre stat1, stat2etc., la situación está pidiendo una tupla: stats = (...).

Entonces, parse_filedevuelva una tupla y almacene la tupla self.stats.

Entonces, por ejemplo, se puede acceder a lo que solía ser llamado stat3con self.stats[2].

unutbu
fuente
Estoy de acuerdo, solo puse self.stat1 a través de self.stat5 para mostrar que había algunas variables de clase a las que estaba asignando. En el código real tengo una solución más elegante.
PythonJin
¿Cómo debería modificarse esto si quiero que la parse_filefunción sea un método del MyClassobjeto? ¿Dónde sería selfnecesario?
n1k31t4
0

En parse_file, tome el selfargumento (como en __init__). Si necesita algún otro contexto, simplemente páselo como argumentos adicionales como de costumbre.

Teo Klestrup Röijezon
fuente
0

Debe declarar parse_file de esta manera; def parse_file(self). El parámetro "self" es un parámetro oculto en la mayoría de los idiomas, pero no en python. Debe agregarlo a la definición de todos los métodos que pertenecen a una clase. Luego puede llamar a la función desde cualquier método dentro de la clase usandoself.parse_file

su programa final se verá así:

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

Creo que su problema es en realidad no sangrar correctamente la función init . Debería ser así

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

     def parse_file():
          pass
Zed
fuente
Tampoco tu código. A menos que coloque el @staticmethoddecorador encima de parse_file
rantanplan
al menos agrega lo que falta selfen tu parse_filemétodo.
rantanplan
Vaya, lo siento, debería haber habido una capa adicional de sangría bajo la línea "class MyClass ():". Lo arreglé arriba, pero la pregunta sigue siendo la misma.
PythonJin