En Python casi todo es un objeto, a diferencia de otros lenguajes, una clase es un objeto también, suena raro pero efectivamente es así:
class Prueba():
pass
p = Prueba()
print(type(Prueba))
print(type(p))
> <class 'type'>
> <class 'Prueba'>
Podemos observar que la clase Prueba
es un objeto del tipo <class 'type'>
y el objeto instanciado es ahora si, del tipo <class 'Prueba'>
. Con esto en mente puede que sea más claro el porque del uso del self
. Supongamos algo parecido a tu ejemplo:
class Persona:
def __init__(self,nom):
self.nombre=nom
def imprimir(self):
print("Nombre: {0}".format(self.nombre))
p1 = Persona("Juan")
p2 = Persona("Pedro")
print(type(Persona))
print(type(p1))
print(type(p2))
> <class 'type'>
> <class 'Persona'>
> <class 'Persona'>
Hemos usado el objeto Persona
del tipo <class 'type'>
(clase) para crear dos nuevos objetos de <class 'Persona'>
. La forma normal de acceder a los métodos sería haciendo esto:
p1.imprimir())
p2.imprimir())
> Juan
> Pedro
Pero lo que en realidad está ocurriendo por debajo, es decir lo que Python hace en realidad, es algo así:
Persona.imprimir(p1))
Persona.imprimir(p2))
> Juan
> Pedro
Una forma de ver esto es que cada instancia p1
y p2
no posee "copias" del método imprimir
no tiene sentido, el método es de la clase Persona
, los datos self.nombre
si, son de cada instancia. De modo que para que Persona
pueda invocar imprimir
pero con los datos de la instancia adecuada, es necesario declarar el método como imprimir(<instancia>)
.
Aclaración: self
es una convención podríamos usar cualquier nombre pero no es recomendable.