Programación Orientada A Objetos - Curso de Python - Hektor Profe
Programación Orientada A Objetos - Curso de Python - Hektor Profe
Presentación
En esta unidad aprenderemos sobre un paradigma que cambió la forma de
entender la programación, introduciendo conceptos tan importantes como las
clases, los objetos y la herencia.
Un poco de historia
Introducción a la POO
Para entender en qué se basa este paradigma (modelo de solución de
problemas), en lugar de empezar con teoría os propongo jugar un poco con dos
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 1/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Lo único que tenéis que hacer es probar ambos códigos (sin necesidad de
analizarlos), luego sacad vuestras propias conclusiones sobre cuál os parece
más útil e intuitivo de aplicar y extender en el mundo real.
Ejemplo estructurado
Código Resultado
print('Cliente no encontrado')
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 2/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
print("==LISTADO DE CLIENTES==")
print(clientes)
print("\n==LISTADO DE CLIENTES==")
print(clientes)
Código Resultado
def __str__(self):
return '{} {}'.format(self.nombre,self.apellidos)
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 3/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Clases y objetos
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 4/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Podéis imaginaros los objetos como un nuevo tipo de dato cuya de nición viene
dada en una estructura llamada clase.
Suelo hacer una metáfora y comparar las clases con moldes de galletas y los
objetos con las galletas en sí mismas. Si bien todas las galletas que se hacen
con el mismo molde tienen la misma forma, cada una adquiere atributos
individuales después del horneado. Cosas como el color, la textura, el sabor...
pueden llegar a ser muy distintas.
Extrapolando el ejemplo, una clase es sólo un guión sobre como deben ser los
objetos que se crearán con ella.
La función type()
Ya he comentado varias veces que en Python todo son clases y objetos, eso se
puede comprobar fácilmente pasando a la función type() cualquier variable o
literal:
Código Resultado
numero = 10
type(numero)
En el código anterior numero es una variable entera, pero si vamos más allá, en
realidad es una instancia del tipo int, una clase muy básica de dato para
almacenar números enteros.
Como curiosidad, incluso las funciones en Python son instancias del tipo
function:
Código Resultado
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 5/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
def hola():
pass
type(hola)
De nición de clase
Código
class Galleta:
pass
Esta es una de nición muy simple de lo que es una galleta, ya que con el pass la
dejo vacía. Luego añadiremos más información, por ahora veamos como crear
galletas con este molde.
Instancias de clase
Para entender bien los objetos debemos tener claras dos cuestiones
fundamentales:
Puede parecer trivial, pero es importante tener claro que los objetos "existen"
sólo durante la ejecución del programa y se almacenan en la memoria del
sistema operativo.
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 6/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código
una_galleta = Galleta()
otra_galleta = Galleta()
Código Resultado
print(una_galleta)
print(otra_galleta)
Código Resultado
print(Galleta)
Código Resultado
print(Galleta)
print(type(una_galleta))
print(una_galleta.__class__)
A su vez las clases tienen un atributo especial name que nos devuelve su
nombre en forma de cadena sin adornos:
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 7/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código Resultado
print(Galleta.__name__)
print(type(una_galleta).__name__)
print(una_galleta.__class__.__name__)
Atributos y métodos
Si hay algo que ilustre el potencial de la POO esa es la capacidad de de nir
variables y funciones dentro de las clases, aunque aquí se conocen como
atributos y métodos respectivamente.
Atributos
Atributos dinámicos
Dado que Python es muy exible los atributos pueden manejarse de distintas
formas, por ejemplo se pueden crear dinámicamente (al vuelo) en los objetos.
Código Resultado
class Galleta:
pass
galleta = Galleta()
galleta.sabor = "salado"
galleta.color = "marrón"
Atributos de clase
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 8/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Aunque la exibilidad de los atributos dinámicos puede llegar a ser muy útil,
tener que de nir los atributos de esa forma es tedioso. Es más práctico de nir
unos atributos básicos en la clase. De esa manera todas las galletas podrían
tener unos atributos por defecto:
Código Resultado
class Galleta:
chocolate = False
galleta = Galleta()
if galleta.chocolate:
print("La galleta tiene chocolate")
else:
print("La galleta no tiene chocolate")
Código Resultado
galleta.chocolate = True
if galleta.chocolate:
print("La galleta tiene chocolate")
else:
print("La galleta no tiene chocolate")
Código Resultado
print(Galleta.chocolate)
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 9/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código Resultado
class Galleta:
chocolate = False
Galleta.chocolate = True
galleta = Galleta()
if galleta.chocolate:
print("La galleta tiene chocolate")
else:
print("La galleta no tiene chocolate")
Métodos
Si por un lado tenemos las "variables" de las clases, por otro tenemos sus
"funciones", que evidentemente nos permiten de nir funcionalidades para
llamarlas desde las instancias.
Código Resultado
class Galleta:
chocolate = False
def saludar():
print("Hola, soy una galleta muy sabrosa")
galleta = Galleta()
galleta.saludar()
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 10/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Sin embargo, al intentar ejecutar el código anterior desde una galleta veréis que
no funciona. Nos indica que el método saludar() requiere 0 argumentos pero se
está pasando uno.
Código Resultado
class Galleta:
chocolate = False
def saludar():
print("Hola, soy una galleta muy sabrosa")
Galleta.saludar()
Los objetos tienen una característica muy importante: son conscientes de que
existen. Y no, no es broma.
Código Resultado
class Galleta:
chocolate = False
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 11/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
def saludar(soy_el_propio_objeto):
print("Hola, soy una galleta muy sabrosa")
print(soy_el_propio_objeto)
galleta = Galleta()
galleta.saludar()
¿Curioso que haya funcionado verdad? Además ¿no os suena de algo ese
resultado que muestra el parámetro que hemos de nido? Se trata de la propia
representación del objeto.
Código Resultado
class Galleta:
chocolate = False
def saludar(soy_el_propio_objeto):
print("Hola, soy una galleta muy sabrosa")
print(soy_el_propio_objeto)
galleta = Galleta()
galleta.saludar()
print(galleta)
Pues sí, podemos acceder al propio objeto desde el interior de sus métodos. Lo
único que como este argumento hace referencia al objeto en sí mismo por
convención se le llama self.
Poder acceder al propio objeto desde un método es muy útil, ya que nos permite
acceder a sus atributos. Fijaros, el siguiente código no funcionaría como
esperamos:
Código Resultado
class Galleta:
chocolate = False
def chocolatear(self):
chocolate = True
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 12/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
galleta = Galleta()
galleta.chocolatear()
print(galleta.chocolate)
Código Resultado
class Galleta:
chocolate = False
def chocolatear(self):
self.chocolate = True
galleta = Galleta()
galleta.chocolatear()
print(galleta.chocolate)
Sea como sea con este ejemplo podemos entender que por defecto el valor de
un atributo se busca en la clase, pero para modi carlo en la instancia es
necesario hacer referencia al objeto.
Métodos especiales
Ahora que sabemos crear métodos y hemos aprendido para qué sirve el
argumento self, es momento de introducir algunos métodos especiales de las
clases.
Constructor
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 13/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código Resultado
class Galleta:
def __init__(self):
print("Soy una galleta acabada de hornear!")
galleta = Galleta()
La nalidad del constructor es, como su nombre indica, construir los objetos.
Por esa razón permite sobreescribir el método que crea los objetos,
permitiéndonos enviar datos desde el principio para construirlo:
Código Resultado
class Galleta:
chocolate = False
Destructor
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 14/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código Resultado
class Galleta:
def __del__(self):
print("La galleta se está borrando de la memoria")
galleta = Galleta()
del(galleta)
En este punto vale comentar algo respecto a los métodos especiales como éste,
y es que pese a que tienen accesores en forma de función para facilitar su
llamada, es totalmente posible ejecutarlos directamente como si fueran
métodos normales:
Código Resultado
class Galleta:
def __del__(self):
print("La galleta se está borrando de la memoria")
galleta = Galleta()
galleta.__del__()
String
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 15/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Por defecto los objetos imprimen su clase y una dirección de memoria, pero eso
puede cambiarse sobreescribiendo el comportamiento:
Código Resultado
class Galleta:
def __str__(self):
return f"Soy una galleta {self.color} y {self.sabor}."
print(galleta)
print(str(galleta))
print(galleta.__str__())
Hay que tener en cuenta que este método debe devolver la cadena en lugar de
mostrar algo por pantalla, ese es el funcionamiento que se espera de él.
Length
Código Resultado
class Cancion:
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 16/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
def __len__(self):
return self.duracion
print(len(cancion))
print(cancion.__len__())
Código Resultado
class Pelicula:
# Constructor de clase
def __init__(self, titulo, duracion, lanzamiento):
self.titulo = titulo
self.duracion = duracion
self.lanzamiento = lanzamiento
print('Se ha creado la película:', self.titulo)
def __str__(self):
return '{} ({})'.format(self.titulo, self.lanzamiento)
class Catalogo:
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 17/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
def mostrar(self):
for p in self.peliculas:
print(p) # Print toma por defecto str(p)
Encapsulación
Finalmente para acabar la introducción vale la pena comentar esta "técnica". No
es santo de mi devoción porque no le veo mucho sentido, pero si venís de otros
lenguajes quizá os interesa conocerla.
Código Resultado
class Ejemplo:
__atributo_privado = "Soy un atributo inalcanzable desde
fuera."
e = Ejemplo()
print(e.__atributo_privado)
Y en los métodos...
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 18/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Código Resultado
class Ejemplo:
def __metodo_privado(self):
print("Soy un método inalcanzable desde fuera.")
e = Ejemplo()
e.__metodo_privado()
¿Qué sentido tiene esto en Python? Ninguno, porque se pierde toda la gracia de
lo que en esencia es el lenguaje: exibilidad y polimor smo sin control
(hablaremos de esto más adelante).
Sea como sea para acceder a esos datos se deberían crear métodos públicos
que hagan de interfaz. En otros lenguajes les llamaríamos getters y setters y es
lo que da lugar a las propiedades, que no son más que atributos protegidos con
interfaces de acceso:
Código Resultado
class Ejemplo:
__atributo_privado = "Soy un atributo inalcanzable desde
fuera."
def __metodo_privado(self):
print("Soy un método inalcanzable desde fuera.")
def atributo_publico(self):
return self.__atributo_privado
def metodo_publico(self):
return self.__metodo_privado()
e = Ejemplo()
print(e.atributo_publico())
e.metodo_publico()
Ejercicio optativo
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 19/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Teoría previa
Nota
Creo que es un ejemplo muy interesante, punto de partida en la programación de grá cos, pero
si consideras que esto no lo tuyo puedes simplemente pasar de largo. Ahora bien, debes ser
consciente de que te vas a perder uno de los ejercicios más interesantes del curso.
El plano cartesiano
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 20/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Puntos y coordenadas
Vectores en el plano
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 21/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
A efectos prácticos no deja de ser una línea formada desde un punto inicial en
dirección a otro punto nal, por lo que se entiende que un vector tiene longitud y
dirección/sentido.
Enunciado
Preparación
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 22/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Añade un método llamado vector, que tome otro punto y calcule el vector
resultante entre los dos puntos.
Nota
La función raíz cuadrada en Python sqrt() se debe importar del módulo math y utilizarla de la
siguiente forma:
import math
math.sqrt(9)
Crea una clase llamada Rectangulo con dos puntos (inicial y nal) que
formarán la diagonal del rectángulo.
Sugerencia
Puedes identi car fácilmente estos valores si intentas dibujar el cuadrado a partir de su
diagonal. Si andas perdido, prueba de dibujarlo en un papel, ¡seguro que lo verás mucho más
claro! Además recuerda que puedes utilizar la función abs() para saber el valor absolute de un
número.
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 23/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
Experimentación
Crea los puntos A(2, 3), B(5,5), C(-3, -1) y D(0,0) e imprimelos por pantalla.
(Optativo) Consulta la distancia entre los puntos 'A y B' y 'B y A'.
Solución
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 24/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 25/26
2/10/2018 Programación Orientada a Objetos | Curso de Python | Hektor Profe
https://www.hektorprofe.net/python/programacion-orientada-a-objetos/#introduccion-a-la-poo 26/26