Hasta el momento hemos implementado inicialmente programas utilizando una estructura lineal, posteriormente vimos las funciones y trabajamos con programación estructurada. A partir de este momento, vamos a utilizar la programación orientada a objetos. Prácticamente todos los lenguajes implementan la posibilidad de la POO (Programación Orientada a Objetos).
Índice
Definición de conceptos de POO
Antes de proseguir explicando la Programación Orientada a Objetos debemos tener más o menos claro la diferencia entre una clase y un objeto, como es normal, estos conceptos los afianzaremos por medio de la práctica pero también es necesaria una base teórica para comprenderlo realmente.
Una clase es una plantilla para la creación de objetos de datos según un modelo definido previamente. Las clases se utilizan para la definición de atributos (variables) y métodos (funciones).
Un objeto sería una instancia de esa clase, es decir, un objeto sería la llamada a una clase. Para que os sea más sencillo, en el tema anterior importábamos el módulo random de python. Este módulo en sí es una clase, al llamar a dicha clase estamos creando una instancia (objeto) de dicha clase. Cuando llamamos al método randint() realmente estamos llamando al método randint de la clase random a través de un objeto creado para dicho fin.
Viendo esta relación, podemos llegar fácilmente a la conclusión de que para crear un objeto, debemos crear previamente la clase, la cual queremos instanciar.
Con la teoría aprendida, vamos a verlo más fácil con un ejemplo.
Implementaremos una clase llamada Persona que tendrá como atributo (variable) el nombre de la persona y dos métodos (funciones). El primero de los métodos inicializará el atributo nombre y el segundo mostrará por pantalla el contenido del mismo. Definir dos instancias (objetos) de la clase Persona.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# creamos la clase class Persona: # creamos la primera funcion # para inicializar el atributo nombre def inicializar(self,nom): self.nombre=nom # creamos el segundo metodo # para mostrar el nombre def mostrar(self): print("Nombre: ",self.nombre) #bloque principal # creamos una instancia de la clase persona persona1=Persona() persona1.inicializar("Marcos") persona1.mostrar() # creamos un objeto de la clase persona persona2=Persona() persona2.inicializar("Ivan") persona2.mostrar() |
Como ya dijimos en una vez, conviene llamar a las variables, clases, etc. Con un nombre que represente aquello que queremos guardar además, de comentarios para asegurarnos que cualquiera pudiera interpretar nuestro programa sin conocerlo.
Para crear nuestra clase utilizamos la palabra clave ‘class’ seguido del nombre de dicha clase. Los métodos se definen utilizando la misma sintaxis que cualquier otra función pero, vemos algo diferente. Todos los métodos tienen como primer parámetro el identificador self que hace referencia al objeto que llamó a dicho método. Dentro de la función diferenciaremos los atributos del objeto utilizando el identificador self seguido de un punto y el nombre del atributo. Separando de esta manera las variables de nuestro objeto con otras variables que utilicemos como apoyo en nuestras funciones.
Para la creación de un objeto, definiríamos el objeto llamado persona1 asignándole el nombre de la clase seguido de los paréntesis de apertura y cierre.
1 2 3 |
persona1=Persona() persona1.inicializar("Marcos") persona1.mostrar() |
Después llamamos al método inicializar al cual le asignaremos el nombre de la persona. Como hemos dicho, el parámetro self hace referencia al objeto al cual llama al método. De esta forma en la función mostrar no le pasamos ningún atributo porque ya estaba definido en el objeto persona1. Además de poder llamar a un atributo, el parámetro self hace referencia al objeto y podemos llamar a una función dentro de la clase utilizando la sintaxis
1 |
self.nombre_del_metodo |
Método especial __init__ de la clase
El método __init__ es una función especial con el objetivo de inicializar los atributos del objeto que creamos.
Implementar este método tiene varias ventajas como son
- Es el primer método en ejecutarse al crear un objeto.
- Podemos asegurarnos de que siempre se va a llamar al crear un objeto.
Veamos en un ejemplo como sería
1 2 3 4 5 6 7 8 9 |
def __init__(self): self.var1=2 self.var2="hola" self.var3=input("Ingresa un valor") def __init__(self,num1,num2): self.num1=num1 self.num2=num2 |
Vemos en el ejemplo que podemos especificar la función y establecer los atributos una vez dentro de ella o, podemos pasar por parámetro los atributos y después igualarlas a los atributos de nuestro objeto.
Hasta ahora hemos visto como definir atributos para una clase anteponiendo la palabra clave self. Los atributos son independientes por cada objeto de la clase, es decir, si definimos tres objetos de la clase alumno, cada uno tendrá un atributo nombre pero cada uno tendrá su valor independiente del resto.
En algunos casos, necesitaremos almacenar algún dato que se comparta entre todos los objetos definidos de una clase, en estas situaciones utilizaremos las variables de clase.
Para definir una variable de clase lo haríamos dentro de la clase pero fuera de sus métodos
1 2 3 |
class Persona: dato1=23 dato2=”string” |
De esta forma podemos inicializar cualquier tipo de dato y sería igual para todos las instancias de la clase que hayan sido creadas.
Método especial __str__
Al igual que podíamos convertir una variable de tipo entero, float, etc… en una de tipo string con la función str(), podemos utilizar un método en una clase para retornar un string.
1 2 |
def __str__(self): return "("+str(self.num1)+","+str(self.num2)+")" |
En este ejemplo, devolvemos un string con el método __str__ que mostrará el dato que le indiquemos al imprimir dicho objeto. Para generar dicho string, debemos concatenar valores fijos como el paréntesis o la coma enteros dobles comillas y convertir a string los atributos que no lo son como vemos en el ejemplo anterior.
Herencia en Python
En Python dos clases además de poder tener una relación de colaboración, también pueden tener una relación de herencia.
La herencia significa que se pueden crear nuevas clases partiendo de otras clases ya existentes, que heredarán todos los atributos y métodos de su clase padre además, de poder añadir los suyos propios.
Por ejemplo, si tenemos una clase llamada vehículo, esta sería la clase padre de las clases coche, moto, bicicleta… Cada una de estas subclases tendría los atributos y métodos de su padre vehículo y aparte tendrían sus propios métodos cada uno de ellos.
Vamos a verlo con un ejemplo práctico
Realizar un programa que conste de un clase Persona con dos atributos nombre y edad. Los atributos se introducirán por teclado y habrá otro método para imprimir los datos.
Declarar una segunda clase llama Empleado que hereda de la clase Persona y agrega el atributo sueldo. Debe mostrar si tiene que pagar impuestos o no (sueldo superior a 3000).
Crear un objeto de cada clase.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# declaramos la clase persona class Persona: # declaramos el metodo __init__ def __init__(self): self.nombre=input("Ingrese el nombre: ") self.edad=int(input("Ingrese la edad: ")) # declaramos el metodo mostrar def mostrar(self): print("Nombre: ",self.nombre) print("Edad: ",self.edad) # declaramos la clase empleado # la clase empleado hereda los atributos y metodos de la clase Persona class Empleado(Persona): # declaramos el metodo __init__ def __init__(self): # llamamos al metodo init de la clase padre # utilizamos la funcion super() para hacer referencia al padre super().__init__() self.sueldo=float(input("Ingrese el sueldo: ")) # declaramos el metodo mostrar def mostrar(self): super().mostrar() print("Sueldo: ",self.sueldo) # declaramos el metodo pagar_impuestos # comprobara si el empleado debe pagar o no def pagar_impuestos(self): if self.sueldo > 3000: print("El empleado debe pagar impuestos.") else: print("El empleado no paga impuestos.") # bloque principal persona1=Persona() persona1.mostrar() empleado1=Empleado() empleado1.mostrar() empleado1.pagar_impuestos() |
La clase Persona como vemos, no tiene nada nuevo y creamos un objeto de la misma forma que lo realizado hasta ahora. Por el contrario en la clase Empleado sí que vemos cosas nuevas.
1 |
class Empleado(Persona): |
Añadiendo entre paréntesis la clase Persona, estamos especificándole que hereda dicha clase. Entonces podemos decir que la clase Empleado heredará los atributos de Persona.
1 2 3 |
def mostrar(self): super().mostrar() print("Sueldo: ",self.sueldo) |
Otra cosa nueva es la función super(), con la cual hacemos referencia a la clase heredada.
Otra forma podría ser
1 2 3 |
def mostrar(self): Persona.mostrar() print("Sueldo: ",self.sueldo) |
De esta otra forma llamamos directamente a la clase en lugar de al método super().
Problemas propuestos
Ejercicio 1
Realizar un programa que conste de una clase llamada Alumno que tenga como atributos el nombre y la nota del alumno. Definir los métodos para inicializar sus atributos, imprimirlos y mostrar un mensaje con el resultado de la nota y si ha aprobado o no.´
Ejercicio 2
Realizar un programa que tenga una clase Persona con las siguientes características. La clase tendrá como atributos el nombre y la edad de una persona. Implementar los métodos necesarios para inicializar los atributos, mostrar los datos e indicar si la persona es mayor de edad o no.
Ejercicio 3
Desarrollar un programa que cargue los datos de un triángulo. Implementar una clase con los métodos para inicializar los atributos, imprimir el valor del lado con un tamaño mayor y el tipo de triángulo que es (equilátero, isósceles o escaleno).
Ejercicio 4
Realizar un programa en el cual se declaren dos valores enteros por teclado utilizando el método __init__. Calcular después la suma, resta, multiplicación y división. Utilizar un método para cada una e imprimir los resultados obtenidos. Llamar a la clase Calculadora.
Ejercicio 5
Realizar una clase que administre una agenda. Se debe almacenar para cada contacto el nombre, el teléfono y el email. Además deberá mostrar un menú con las siguientes opciones
- Añadir contacto
- Lista de contactos
- Buscar contacto
- Editar contacto
- Cerrar agenda
Ejercicio 6
En un banco tienen clientes que pueden hacer depósitos y extracciones de dinero. El banco requiere también al final del día calcular la cantidad de dinero que se ha depositado.
Se deberán crear dos clases, la clase cliente y la clase banco. La clase cliente tendrá los atributos nombre y cantidad y los métodos __init__, depositar, extraer, mostrar_total.
La clase banco tendrá como atributos 3 objetos de la clase cliente y los métodos __init__, operar y deposito_total.
Ejercicio 7
Desarrollar un programa que conste de una clase padre Cuenta y dos subclases PlazoFijo y CajaAhorro. Definir los atributos titular y cantidad y un método para imprimir los datos en la clase Cuenta. La clase CajaAhorro tendrá un método para heredar los datos y uno para mostrar la información.
La clase PlazoFijo tendrá dos atributos propios, plazo e interés. Tendrá un método para obtener el importe del interés (cantidad*interés/100) y otro método para mostrar la información, datos del titular plazo, interés y total de interés.
Crear al menos un objeto de cada subclase.
Además tenéis la lista completa de ejercicios en nuestro repositorio en github.
Con esto acabamos el undécimo capítulo de nuestro curso de python 3.5. Si tienen cualquier duda relacionada con el contenido explicada en este capítulo, pueden exponerla en sus comentarios y le ayudaremos a resolverla lo antes posible. Nos vemos en el siguiente capítulo donde veremos una nueva forma de redefinir operadores con objetos.
<- Anterior | Volver al índice | Siguiente -> |
Hola, buenas noches, gracias por tus ejercicios de clases y objetos en Python; pero en el ejercicio 5 que consiste en realizar una clase para administrar una agenda de contactos, estoy intentando agregar la opción para eliminar contactos pero no encuentro la manera de hacerlo. Por favor me puedes ayudar y explicar como agregar la opcion para eliminar contactos.
Gracias
Hola Juan,
En el ejercicio 5 de la lista de contactos de la agenda, si te fijas el array “contactos” es una lista.
Para la eliminación de un elemento de la lista puedes utilizar la función pop() tal y como indica la documentación de python, te adjunto el enlace https://docs.python.org/3/tutorial/datastructures.html
A esta función pop() tendrías que pasarle la posición que ocupa en el array, y para obtener el mismo puedes por ejemplo fijarte en la función buscar() del ejemplo.
Dicho esto, te pongo un ejemplo con dicha función:
# pasamos la función de buscar
contacto=self.buscar()
# esta función anterior nos devolverá la posición del mismo en la variable x
# y posteriormente lo eliminamos con la función pop()
self.contactos.pop(contacto)
Con esta indicación dejo a tu elección como poner la función para eliminar el mismo y si tienes alguna duda más al respecto no dudes en preguntar.
Saludos
Hola, gracias por tu explicación
Buenas tardes.
Estoy en el mismo paso que tú. Quiero implementar un método de borrar un contacto.
Por la explicación, he ideado está posible solución. Pero lamentablemente no me ha funcionado.
Código:
Hola! un poco tarde mi respuesta, pero espero te ayude!
Segun el ejercicio, el almacena los contactos en diccionarios dentro de una lista, es decir, cada contacto es un diccionario dentro de una lista general.
Tomando en cuenta esto, para eliminar un contacto simplemente hariamos lo siguiente:
contactos = [] #Esta es la lista general
contactos.append({‘nombre’:”Luis”,’telf’:”9911″,’email’:”luis.sk”})# Esto es la accion que hace el metodo anadir
contactos.append({‘nombre’:”Pedro”,’telf’:”2345″,’email’:”pedro.sk”})# Esto es la accion que hace el metodo anadir
#Anadiendo un metodo eliminar, haria lo siguiente:
for x in range(len(contactos)):
# “Pedro” seria el nombre del contacto que estoy buscando eliminar
if contactos[x][“nombre”] == “Pedro”:
#en caso de que exista, con .pop() lo elimino de la lista contactos, .pop() recibe el indice, el cual esta quedando en la variable “x” dentro del for loop.
#Eliminando por indice, te servira si la agenda tiene 1 o 10.000 contactos.
contactos.pop(x)
Opcionalmente podrias agregar un else y retornar un mensaje en caso de que el nombre del contacto no se encuentre, o perfeccionarlo para que se pueda buscar mediante el email y telefono tambien.
Saludos!
He buscado en Internet y visitado muchas páginas para incirme en la POO. Esta es la más clara y pedagógica de todas las que he encontrado. Puedo afirmar que ésta Web sí “está orientada al alumno”. Muchas gracias
Estoy de acuerdo contigo.
Hola, saludos.
Soy nuevo en esto y es la primera vez que veo un arreglo de una lista de esta forma:
self.contactos[x][‘nombre’]
Podrias explicarme la sintaxis.
Por otro lado, al agregar datos de esta forma a la lista ¿no se convierte en un diccionario? (lo digo por las llaves)
self.contactos.append({‘nombre’:nom,’telf’:telf,’email’:email})
Hola Marcos,
En el caso de self.contactos[x][‘nombre’] la sintaxis sería que estarías llamando a la lista llamada contactos, obteniendo en [x] el elemento correspondiente de la lista. Como el elemento 0 de la lista, en este caso es un diccionario, con el siguiente campo [‘nombre’] estamos llamando al campo nombre del diccionario.
Con respecto a la segunda pregunta, lo que tenemos aquí es una lista y cada elemento de la lista es un diccionario en el cual guardamos los datos.
Para que lo veas más claro, si le añades varios elementos a la lista, y después la imprimieses, tendrías un resultado donde contactos tendría los siguientes elementos:
({‘nombre’:’nombre1′,’telf’:’telf1′,’email’:’email1′},{‘nombre’:’nombre2′,’telf’:’telf2′,’email’:’email2′})
En este ejemplo, tenemos la lista contactos que dispone de dos elementos y cada uno de estos elementos es un diccionario independiente donde tenemos los datos del contacto.
Espero haber resuelto tus dudas, si tienes alguna más no dudes en comentarla.
Saludos
Holaa !!! como van
Estuve viendo estos ejercicios y vaya que son muy completos, muchas gracias por compartir gracias a ustedes el conocimiento no se pierde.
Tengo unas dudas respecto al ejercicio de la agenda, en esta linea por ejemplo: self.contactos[data][‘nombre’]=nom .
eso es una forma de adicionar valores a una lista o es un diccionario al cual se le asigna la variable nom ?
Gracias !!
Hola Jairo,
En ese caso que indicas, es un diccionario que ya existe, y lo que se hace es modificar el valor del campo nombre del diccionario.
Saludos
Hola, en el ejercicio de la Agenda, me costo entender el porque una lista de diccionarios pero al final lo entendi. Gracias por tu ayuda.
Pero en ese mismo ejercicio si quiero Editar un contacto que no existe, me salta error. Te lo dejo como comentario, no es una critica. Faltaba mas. Gracias por tu aporte!!!
Hola Graciela,
Perfecto, sí, salta un error debido a que el mismo no existe y tampoco se ha controlado en el ejercicio dicho error. En futuras actualizaciones del curso se tratará en profundidad el control de errores y excepciones.
Gracias por leernos!
En el ejemplo de la Herencia se repite el paso de ingresar el nombre y la edad. Habrá alguna solución para eso.
Hola, llevo un tiempo sin poder resolver ese ejercicio. Me podrían ayudar?
Desarrollar un programa que considere lo siguiente:
1. Una clase Club y otra clase Socio.
2. La clase Socio debe tener los siguientes atributos: nombre y la antigüedad en el club (en años).
3. En el método__init___ de la clase Socio pedir la carga por teclado del nombre y su antigüedad.
4. La clase Club debe tener como atributos 3 objetos
de la clase Socio.
class Socio:
def __init__(self):
self.nombre=str(input(“ingrese nombre :”))
self.antiguedad=int(input(“ingrese antiguedad en el club :”))
self.telefono=123456789
def mostrar(self):
print(“nombre:”,self.nombre)
print(“aniguedad:”,self.antiguedad)
print(“telefono:”,self.telefono)
class Club(Socio):
print(“——-CLUB——-“)
pass
club=Club()
club.mostrar()
hola buen dia, que buen contenido compartes, muchas gracias.
tengo una pregunta, aunque no hay ejercicio como tal de lo que voy a preguntar, quisiera que me ayudaras porfa.
estoy haciendo un programa que venda boletos de bus, tipo, cuando vas a viajar y te muestran que asientos están disponibles, entonces quiero me diga que asientos de un bus están disponibles y cuales no, la verdad es que no he encontrado por ningún lado como hacerlo. agradezco su ayuda.
Hola sebastian,
Por dar alguna idea, podrías almacenar los valores en un array y luego consultar el mismo para saber el estado del asiento, en el caso del ejemplo que indicas. Te animo a que desarrolles tu propio código, y si tienes alguna duda con el mismo no dudes en exponerla.
Saludos
Realizar una clase que administre una Biblioteca. Se debe almacenar para cada libro el nombre y autor. Además deberá mostrar un menú con las siguientes opciones:
Añadir libro
Lista de libros
Buscar libro
Editar libro
Salir del sistema