Contenido del capítulo

Aprende de manera fácil cómo funciona el método __init__ en Python en las clases. Un tema que a menudo se dificulta para quienes empiezan en programación.

Duración estimada de todo el contenido:
Duración del vídeo:
No tiene ejercicios Contiene 1 vídeo.
Tabla de contenidos
Logo

    ¿Qué es el método __init__?

    El método __init__ es un método especial de Python, que podemos incluir en las clases. Por norma general, encontraremos este método en cada clase.

    El método __init__() de Python
    El método __init__() de Python

    El nombre del método __init__ tiene dos guiones bajos delante del init, y dos más después. Si pones solo uno en cada lado, no te va a funcionar.

    Fíjate bien en los nombres de otros elementos de Python, ya que hay muchos que también se escriben con dos guiones bajos a cada lado.

    El nombre del método __init__ proviene de la palabra en inglés denominada como initialize, que en español significa inicializar.

    Por lo tanto, podríamos denominar a este método como método inicializador o constructor.

    Espacio publicitario

    ¿Para qué sirve el método __init__?

    El método __init__ es un método que no necesita ser llamado explícitamente. Este método se llama automáticamente por parte del intérprete de Python, al crear una instancia de una clase (hablo en tiempo de ejecución, no me refiero a cuando escribes el código).

    Gracias a este método constructor, podrás dar un estado inicial al objeto.

    Veamos un ejemplo práctico para aclarar este concepto teórico.

    La siguiente clase Usuario, está funcionando correctamente:

    class Usuario:
        # Atributos
        nombre = "Sin nombre"
        apellidos = "Sin apellidos"
        edad = 0
        direccion = "Sin dirección"
        telefono = "Sin teléfono"
    
        # Métodos
        def iniciar_sesion(self):
            print("El usuario ha iniciado sesión")
    
        def cerrar_sesion(self):
            print("El usuario ha cerrado sesión")
    
        def cambiar_nombre_perfil(self):
            print("Se cambió el nombre")

    No obstante, ¿cómo harías para crear tres objetos con esta clase, e inicializar todos sus atributos?

    Tendrías que ir reasignando uno por uno.

    Aquí tienes un ejemplo con un solo objeto:

    # Instanciación
    usuario_1 = Usuario()
    
    # Inicialización de datos
    usuario_1.nombre = "Enrique"
    usuario_1.apellidos = "Barros Fernández"
    usuario_1.edad = 32
    usuario_1.direccion = "C/Programación Fácil n.º 34"
    usuario_1.telefono = "123456789"

    Ahora, haz esto mismo con dos objetos más, o con el número que sea, por ejemplo, 500. Son muchas líneas, ¿verdad?

    Para mejorar este proceso de construcción inicial de los objetos, se creó el método __init__. Gracias a él, podrás dar un estado inicial de una forma muy sencilla y práctica.

    Atributos de clase y de instancia

    Estos atributos de clase dan un mismo valor a todos los objetos instanciados. Por ejemplo, si instancio dos objetos de tipo Usuario, estaré creando dos objetos con el valor "Sin nombre", en el atributo nombre.

    Mientras que con los atributos de instancia, podrán ser diferentes desde un principio, en cada objeto.

    Esto lo irás entendiendo mejor con los siguientes ejemplos.

    Espacio publicitario

    Añadir el método __init__ a una clase

    Vamos a sustituir en el ejemplo anterior, todos los atributos de clase, por atributos de instancia, utilizando el método __init__:

    class Usuario:
        def __init__(self, nombre, apellidos, edad, direccion, telefono):
            self.nombre = nombre
            self.apellidos = apellidos
            self.edad = edad
            self.direccion = direccion
            self.telefono = telefono
    
        # Métodos
        def iniciar_sesion(self):
            print("El usuario ha iniciado sesión")
    
        def cerrar_sesion(self):
            print("El usuario ha cerrado sesión")
    
        def cambiar_nombre_perfil(self):
            print("Se cambió el nombre")

    ¡Genial!, ya tenemos el método __init__ listo para construir objetos.

    Por el momento, hasta que lo explique, ignora completamente el parámetro self. Simplemente, sigue poniéndolo en los paréntesis de los métodos.

    Ahora, creemos un objeto a partir de la clase. Esta vez, en lugar de inicializar cada atributo de la forma que has visto en el ejemplo anterior, lo haremos así, de una forma mucho más eficiente:

    # Instancia
    usuario_1 = Usuario("Enrique", 
                        "Barros Fernández",
                        32,
                        "C/Programación Fácil n.º 34", 
                        "123456789")
    
    # Probamos un atributo
    print(usuario_1.nombre)
    Resultado en la consola
    Enrique

    En Python, entre los paréntesis, puedes colocar los elementos con saltos de línea y tabulaciones, ya que estos no afectan al intérprete.

    La colocación del ejemplo de código anterior, es para una mayor legibilidad, evitando poner todos los argumentos en fila, en una línea muy larga.

    Gracias al método __init__, podemos dar un estado inicial a los atributos de los objetos en la propia instanciación.

    Al crearse el objeto, Python llama automáticamente al método. Esto ocurre porque es un método especial. No tenemos que llamarlo nosotros, tal y como he indicado anteriormente.

    Al crear un objeto de una clase, que tiene método __init__, se hace una llamada implícita. Lo llama el intérprete de Python internamente.

    Fíjate que los argumentos utilizados en el ejemplo, son posicionales (deben seguir el orden de declaración del __init__). No obstante, puedes utilizar argumentos de clave:

    usuario_1 = Usuario(apellidos = "Barros Fernández",
                        edad = 32, 
                        direccion = "C/Programación Fácil n.º 34", 
                        telefono = "123456789", 
                        nombre = "Enrique")

    En este caso, el orden no importa.

    ¿Qué ocurre si no quiero inicializar un atributo en la instancia?

    Supongamos que quiero inicializar de momento solo el atributo nombre, y el resto no.

    Entonces, ocurrirá la siguiente excepción:

    # Instancia
    usuario_1 = Usuario(nombre = "Enrique")
    Error en la consola
    TypeError: Usuario.__init__() missing 4 required positional arguments: 'apellidos', 'edad', 'direccion', and 'telefono'
    Error de tipo: Faltan 4 argumentos posicionales obligatorios en el método init() de la clase Usuario: 'apellidos', 'edad', 'direccion', y 'telefono'

    Como es lógico, al igual que con las funciones, si tenemos cinco parámetros, hay que escribir cinco argumentos en la llamada. Entonces quiere decir que el método __init__ nos obliga a inicializar los objetos con los parámetros que se especifiquen en él.

    Espacio publicitario

    Si en la clase quieres tener también atributos de clase, junto a los de instancia, los puedes tener perfectamente. Estos funcionan de forma independiente al método constructor.

    Aquí tienes un ejemplo usando un atributo de clase y los de instancia a la vez:

    class Usuario:
        # Atributos de clase
        hora_ultimo_inicio = None
    
        # Atributos de instancia
        def __init__(self, nombre, apellidos, edad, direccion, telefono):
            self.nombre = nombre
            self.apellidos = apellidos
            self.edad = edad
            self.direccion = direccion
            self.telefono = telefono

    En este ejemplo, cuando instanciemos un objeto de esta clase, le tendremos que dar los cinco valores obligatorios; los iniciales. Pero el atributo de clase hora_ultimo_inicio, tendrá por defecto ese valor None, que podrá ser reasignado posteriormente, al igual que cualquier atributo del __init__.

    Sin embargo, sin reasignaciones sobre el propio atributo hora_ultimo_inicio, no le podemos dar un estado inicial diferente para cada objeto, solo lo controlamos después con la reasignación.

    En el siguiente ejemplo, se muestra cómo se da un estado inicial a los atributos de instancia, cómo se reasigna uno de ellos (nombre) y cómo se reasigna el atributo de clase (hora_ultimo_inicio).

    # Estado inicial a los atributos de instancia
    usuario_1 = Usuario("Enrique", 
                       "Barros Fernández",
                        32, 
                        "C/Programación Fácil n.º 34", 
                        "123456709")
    
    # Reasignaciones
    usuario_1.nombre = "Quique"
    usuario_1.hora_ultimo_inicio  = ("20/12/2025")
    
    # Probamos los atributos
    print(usuario_1.nombre)
    print(usuario_1.hora_ultimo_inicio)
    Resultado en la consola
    Quique
    20/12/2025

    Nombres en el __init__

    Puede ser que no veas clara la diferenciación entre lo que son los nombres de atributo, y los nombres de parámetro en la declaración del __init__.

    En el siguiente ejemplo, podrás ver una clara diferencia entre ambos:

    def __init__(self, parametro_1, parametro_2, parametro_3, parametro_4, parametro_5):
        self.atributo_1 = parametro_1
        self.atributo_2 = parametro_2
        self.atributo_3 = parametro_3
        self.atributo_4 = parametro_4
        self.atributo_5 = parametro_5

    Cuando instanciamos y damos los valores iniciales con argumentos, estos se pasan a los parámetros del __init__. Tales valores se van asignando a los atributos correspondientes, tal y como puedes ver en el ejemplo.

    Lo que quiero dejar claro, es que no tiene porqué ponerse el mismo nombre de atributo que de parámetro.

    Espacio publicitario

    Puedes escribir un __init__ como el del ejemplo de código. Este va a funcionar correctamente.

    No obstante, normalmente, verás escrito el mismo nombre de atributo que de parámetro. Esto con el fin de dejar claridad en el código.

    Valores por defecto en el __init__

    Otra posibilidad es la de tener valores iniciales por defecto en el propio __init__.

    Se trata de dejar atributos inicializados de la siguiente forma (fíjate en el atributo direccion):

    class Usuario:
        # Atributos de instancia
        def __init__(self, nombre, apellidos, edad, telefono):
    
            self.nombre = nombre
            self.apellidos = apellidos
            self.edad = edad
            self.telefono = telefono
    
            self.direccion = "Sin dirección"

    Si dejamos valores por defecto en ciertos atributos de instancia, no será necesario añadir el valor correspondiente en la instanciación.

    Según el código de ejemplo, todos los objetos, serán instanciados con ese valor "Sin dirección", por defecto en el atributo direccion.

    Ten en cuenta, que en este caso no se está pasando el atributo direccion como parámetro del __init__, ya que lo estamos inicializando directamente desde la clase.

    Espacio publicitario




    Espacio publicitario




    Espacio publicitario