Contenido del capítulo

Aprende de manera fácil cómo funciona el parámetro self 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:
Contiene 6 ejercicios Contiene 1 vídeo.
Tabla de contenidos
Logo

    ¿Qué es self de Python?

    El parámetro especial self de Python
    El parámetro especial self de Python

    Todos los métodos de clase llevan un primer parámetro obligatorio llamado self. Esto mismo lo has visto en los métodos de ejemplo de la clase Usuario de capítulos anteriores.
    Por ejemplo, los tres siguientes métodos lo están utilizando:

    # 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")

    Espacio publicitario

    Este parámetro debe ser siempre el primero. Es decir, en métodos que tengan varios parámetros, esa será siempre su posición.

    Aunque crees un método que no lleva parámetros, deberá estar self presente, ya que si lo dejas sin poner, recibirás un error como este al intentar llamarlo:

        . . .
    
        def cerrar_sesion():
            print("El usuario ha cerrado sesión")
    
        def cambiar_nombre_perfil(self):
            print("Se cambió el nombre")
            
        . . .
    
    usuario_1.cerrar_sesion()
    Error en la consola
    TypeError: Usuario.cerrar_sesion() takes 0 positional arguments but 1 was given
    El método cerrar_sesión() de la clase Usuario espera 0 argumentos posicionales, pero se le proporcionó 1.

    El error demuestra que el intérprete de Python está pasando el valor de self internamente, ya que en la consola nos dice que el método no espera argumentos, pero que se le ha pasado 1, siendo que no se le está pasando ninguno explícitamente.

    El parámetro self sirve para representar al propio objeto. Gracias a esto, podemos acceder mediante él, a los atributos y métodos de una clase.

    Sin self, los métodos de una clase no tendrían forma de saber a qué instancia de la clase se están aplicando.

    Quiere decir que self se emplea como comodín, para reemplazarse por el objeto con el que se llama a un atributo de la clase, o un método, dentro de ella.

    Por ejemplo, tenemos dos objetos de Usuario:

    # Instancias
    usuario_1 = Usuario("Enrique", "Barros Fernández",
                         32, "C/Programación Fácil n.º 34", 
                         "123456789")
    usuario_2 = Usuario("Adriana", "Barca López",
                         28, "Sin dirección", 
                         "987654321")

    Cuando llamamos a un método con un objeto como usuario_2.método(argumento1, argumento2, argumento3), Python lo convierte automáticamente en método(usuario_2, argumento1, argumento2, argumento3).

    El nombre del propio objeto que realiza la llamada, es el que se le pasa implícitamente al parámetro self. De esta forma, self nos automatiza y simplifica la sintaxis, ya que si no, tendríamos que estar indicando el objeto cada vez que llamásemos a un método.

    Por ejemplo:

    Usuario.iniciar_sesion(usuario_2)

    Que, de hecho, esta sintaxis es válida, pero mucho más confusa bajo mi punto de vista.

    En lugar de tener que hacer uso de esa sintaxis, podemos utilizar de forma correcta el parámetro self, y hacer uso de esta:

    usuario_2.iniciar_sesion()

    Así, el intérprete ya se encarga de hacer el “trabajo sucio”.

    El nombre self es una convención

    El nombre de parámetro self, no es una palabra reservada de Python. Esto quiere decir, que llamarlo así, es una convención; lo puedes llamar de otra forma perfectamente.

    Mira este ejemplo:

    def __init__(objeto, color, longitud_metros, ruedas):
        objeto.color = color
        objeto.longitud_metros = longitud_metros
        objeto.ruedas = ruedas

    Ten en cuenta, que si utilizas otro nombre, deberás seguir usando ese mismo, como puedes ver en el ejemplo.

    Espacio publicitario

    Personalmente, no cambiaría el self por otro nombre, ya que si alguien tiene que editar tu código, le vas a complicar más la tarea de leerlo y entenderlo.

    Si no entiendas todavía al 100% como funciona self, no te preocupes, puesto que lo importante es que lo apliques siempre a los atributos de instancia y a los métodos, tal y como te he enseñado. Con el tiempo irás ganando mayor profundidad en tus conocimientos de la programación orientada a objetos.

    En otros lenguajes de programación, como puede ser Java, el equivalente a self de Python, es this.

    Utilizar atributos en los métodos de clases

    Ahora, vamos a intentar modificar uno de los tres métodos de la clase Usuario. Por ejemplo, iniciar_sesion().

    Sencillamente, quiero que consigas, que cuando se llame mediante un objeto con este método, muestre el propio valor del atributo nombre, del objeto de tipo Usuario.

    Empezamos con la clase así, y dos objetos:

    class Usuario:
        # 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
    
        # Métodos
        def iniciar_sesion(self):
            print("El usuario ha iniciado sesión")
    
    # Instancias
    usuario_1 = Usuario("Enrique", "Barros Fernández",
                        32, "C/Programación Fácil n.º 34", 
                        "123456789")
    usuario_2 = Usuario("Adriana", "Barca López",
                        28, "Sin dirección", 
                        "987654321")

    Podríamos pensar, que haciendo esto, nos serviría:

    def iniciar_sesion(self):
        print(f"El usuario {nombre} ha iniciado sesión")

    Sin embargo, al llamar al método, ocurre el siguiente error:

    usuario_1.iniciar_sesion()
    Error en la consola
    NameError: name 'nombre' is not defined. Did you mean: 'self.nombre'?   
    Error de nombre: el nombre 'nombre' no está definido. ¿Quizás querías decir 'self.nombre'?

    El error nos indica muy bien la solución. Si dentro de la clase, cada vez que llamamos a un atributo no hacemos la referencia al objeto con self, nos ocurrirá este fallo.

    Para evitarlo, solo pon self:

    def iniciar_sesion(self):
        print(f"El usuario {self.nombre} ha iniciado sesión")

    Ahora, al llamar al método con los dos objetos, se reemplazará internamente self.nombre por usuario_1.nombre y usuario_2.nombre, respectivamente:

    usuario_1.iniciar_sesion()
    usuario_2.iniciar_sesion()
    Resultado en la consola
    El usuario Enrique ha iniciado sesión
    El usuario Adriana ha iniciado sesión

    Espacio publicitario




    Espacio publicitario


    Ejercicios de Python para resolver

    11. Crea una clase llamada Perro, con método __init__, que conste de los siguientes atributos:

    • nombre
    • raza
    • edad
    • color

    Creamos la clase Perro, con el siguiente método __init__:

    class Perro:
        def __init__(self, nombre, raza, edad, color):
            self.nombre = nombre
            self.raza = raza
            self.edad = edad
            self.color = color

    12. Crea dos objetos de tipo Perro.

    Creamos dos objetos de tipo Perro:

    perro1 = Perro("Estrella", "Golden Retriever", 4, "Dorado")
    perro2 = Perro("Sr. Nieves", "Husky Siberiano", 3, "Gris y blanco")

    13. Añade un método llamado ladrar(). Este, al ser llamado, deberá indicar una frase como esta:

    Chester ha ladrado.

    El método deberá ir colocado después del método __init__:

     def ladrar(self):
            print(f"{self.nombre} ha ladrado.")

    14. Llama con los dos objetos, al método ladrar(). Este deberá mostrar el nombre de cada perro, con la frase creada en el ejercicio anterior.

    Hacemos una llamada con cada objeto.

    Te dejo el código completo de la práctica, por si te has perdido en algún punto:

    class Perro:
        def __init__(self, nombre, raza, edad, color):
            self.nombre = nombre
            self.raza = raza
            self.edad = edad
            self.color = color
    
        def ladrar(self):
            print(f"{self.nombre} ha ladrado.")
    
    perro1 = Perro("Estrella", "Golden Retriever", 4, "Dorado")
    perro2 = Perro("Sr. Nieves", "Husky Siberiano", 3, "Gris y blanco")
    
    perro1.ladrar()
    perro2.ladrar()
    Resultado en la consola
    Estrella ha ladrado.
    Sr. Nieves ha ladrado.

    15. En la instanciación, se está recibiendo un error de tipo TypeError.

    ¿Podrías solucionarlo?

    class Vehiculo():
    
        def __init__(self, color, longitud_metros, ruedas):
            self.color = color
            self.longitud = longitud_metros
            self.ruedas = ruedas
    
    vehiculo_1 = Vehiculo ("rojo", 5, 4, "Ford")

    Si ejecutas el código, en la consola podrás ver el siguiente error:

    Error en la consola
    TypeError: Vehiculo.__init__() takes 4 positional arguments but 5 were given
    Error de tipo: Vehiculo.init() toma 4 argumentos posicionales, pero se dieron 5

    El error indica que el objeto tiene 4 argumentos posicionales, pero se han pasado 5.

    El método espera los siguientes argumentos:

    • self (Lo pasa el intérprete. No lo escribimos en la instanciación)
    • color
    • longitud
    • ruedas

    En el ejercicio estoy haciendo la llamada con estos argumentos:

    • self (objeto)
    • color ("rojo")
    • longitud (5)
    • ruedas (4)
    • "Ford" (no tiene parámetro. Este argumento sobra)

    La instanciación podría quedar así:

    vehiculo_1 = Vehiculo ("rojo", 5, 4)


    Espacio publicitario