Recordemos que ya hemos creado la clase Coche con cuatro propiedades y dos métodos.
class Coche():
largo = 426 # atributo de clase
ancho = 181
ruedas = 4
enmarcha = False
def arrancar(self):
print("Arrancando...")
self.enmarcha=True
def estado(self):
if self.enmarcha:
return "El coche está en marcha"
else:
return "El coche está parado"
miCoche = Coche() # instanciación del primer objeto, así creamos el objeto miCoche
miCoche.arrancar() # accedemos al método arrancar
miCoche.estado() # accedemos al método estado
print("ruedas: ", miCoche.ruedas) # accedemos a la propiedad ruedas
print("ancho: ", miCoche.ancho) # accedemos a la propiedad ancho
print("largo: ", miCoche.largo) # accedemos a la propiedad largo
print("¿en marcha?: ", miCoche.enmarcha) # accedemos a la propiedad enmarcha
Arrancando... ruedas: 4 ancho: 181 largo: 426 ¿en marcha?: True
Crearemos un segundo objeto de la clase Coche que necesariamente ha de tener distinto nombre.
tuCoche = Coche() # instanciación del segundo objeto, así creamos el objeto tuCoche
tuCoche.estado() # accedemos al método estado que indicará 'parado'
# ya que aún no hemos arrancado
print("ruedas: ", tuCoche.ruedas) # accedemos a la propiedad ruedas
print("ancho: ", tuCoche.ancho) # accedemos a la propiedad ancho
print("largo: ", tuCoche.largo) # accedemos a la propiedad largo
print("¿en marcha?: ", tuCoche.enmarcha) # accedemos a la propiedad enmarcha
ruedas: 4 ancho: 181 largo: 426 ¿en marcha?: False
Los dos objetos miCoche y tuCoche comparte algunas propiedades (largo, ancho, ruedas) pero en otras difieren (enmarcha).
El primer coche está en marcha, porque se arrancó, y el segundo no.
Sería buena idea que el método 'arrancar' se encargara también de informar sobre el estado del coche, diciendo si está arrancado o no. Por ello, el método 'arrancar' absorberá al método 'estado', que dejará de existir.
Vamos a añadir lo que hace el método 'estado' al método 'arrancar', para ello añadiremos el parámetro 'arrancamos'.
class Coche():
largo = 426
ancho = 181
ruedas = 4
enmarcha = False
def arrancar(self, arrancamos):
self.enmarcha = arrancamos # La variable enmarcha será True o False según lo que nos pasen por el parámetro arrancamos
if self.enmarcha:
return "El coche está en marcha"
else:
return "El coche está parado"
def estado(self):
print(f"El coche tiene {self.ruedas} ruedas, un ancho de {self.ancho} y un largo de {self.largo}.")
miCoche = Coche()
miCoche.estado()
print(miCoche.arrancar(True)) # ahora el método arrancar necesita obligatoriamente un argumento
El coche tiene 4 ruedas, un ancho de 181 y un largo de 426. El coche está en marcha
tuCoche = Coche()
print(tuCoche.arrancar(False)) # para el objeto 'tuCoche' le pasamos como argumento False
El coche está parado
En la línea anterior hemos llamado al método arrancar.
tuCoche.arrancar(False)
El método arrancar vemos que tiene dos parámetros:
Hemos puesto un print en:
Pero no hemos puesto un print en:
Ambos son métodos aplicados sobre el mismo objeto. El motivo es que el método estado ya lleva un print en su definición y por el contrario el método arrancar no lleva ningún print en su definición y si se ejecuta sin poner un print no llegaríamos a ver lo que se retorna (al ejecutar en un archivo .py).
Es habitual que las características comunes de los objetos que se se creen y que pertenezcan a una clase formen parte del denominado 'estado inicial' de esa clase.
Esto supone que en el momento en el que se instancia un objeto concreto perteneciente a una clase ya se le aplica ese estado inicial con todas sus propiedades que consideremos interesantes que sean comunes.
El estado inicial se define con un constructor.
Es un método inicial que proporciona el estado inicial de los objetos creados.
Es una forma de especificar claramente cuál será el estado inicial de los objetos que pertenezcan a esa clase.
Por convenio el constructor va arriba al crear la clase.
Para crear un método constructor meteremos todas las propiedades comunes dentro de una estructura en forma de función con esta sintaxis:
def __init__(self):
Python llama automáticamente al método constructor cuando se crea una instancia.
El método constructor contiene los atributos que deseamos tenga un objeto cuando se inicializa, lo que permite construir objetos con propiedades predefinidas.
El parámetro self
es obligatorio, hace referencia al propio objeto. Por costumbre se llama self en Python pero el nombre puede ser otro. En JAVA y en JS se llama this.
class Coche():
def __init__(self): # aquí se crea el constructor. El método __init__ es llamado al crear el objeto
self.largo = 426 # las propiedades llevan un self. que las antecede
self.ancho = 181 # todas las variables que se crean en el constructor son
self.ruedas = 4 # los atributos de clase y son comunes a todos los objetos
self.enmarcha = False # que se crean de esta clase
def arrancar(self, arrancamos):
self.enmarcha = arrancamos
if self.enmarcha:
return "El coche está en marcha"
else:
return "El coche está parado"
def estado(self):
print(f"El coche tiene {self.ruedas} ruedas, un ancho de {self.ancho} y un largo de {self.largo}.")
miCoche = Coche() # Al instanciar un objeto, aunque no se pasen atributos implícitamente, va self
print(miCoche.arrancar(True))
miCoche.estado()
El coche está en marcha El coche tiene 4 ruedas, un ancho de 181 y un largo de 426.
Vemos que el código anterior funciona igual que sin la creación del constructor en este ejemplo sencillo, pero ahora tenemos la ventaja de tener todas las propiedades, con las que se inicia un objeto por defecto, agrupadas al inicio.
El parámetro self debe ir puesto el primero en el método constructor y en todos los demás métodos, ya que hace referencia al propio objeto y es lo que espera encontrar el intérprete de Python.
Al instanciar un objeto automáticamente se llama al método constructor y se aplican a ese objeto todos los atributos de clase, que son comunes para todos los objetos de esa clase.
Modificando atributos.
Vamos a cambiar alguna de las propiedades de un objeto después de haber sido creado.
Cuando el objeto se instancia (se crea) toma las propiedades que le da el constructor, pero luego podemos cambiarlas.
miCoche.ruedas += 2
miCoche.estado()
El coche tiene 6 ruedas, un ancho de 181 y un largo de 426.