PROGRAMACIÓN ORIENTADA A OBJETOS EN
PYTHON
La Programación Orientada a Objetos (POO) es un paradigma fundamental en Python, que
no solo enriquece el lenguaje con poderosas herramientas, sino que también facilita el
desarrollo de software complejo y escalable.
En la programación orientada a objetos, los objetos son entidades que representan cosas
del mundo real o conceptos abstractos. Cada objeto tiene propiedades (llamadas
atributos) y comportamiento (llamados “métodos”).
• Los atributos son características que describen el estado de un objeto
• Los métodos son las acciones que un objeto puede realizar o los servicios que
puede proporcionar.
La programación orientada a objetos se centra en la modularidad y la reutilización de
código.
Permite organizar un programa en clases, que son plantillas o modelos para crear objetos.
Una clase define las propiedades y los métodos comunes que tienen los objetos de ese
tipo.
Luego, se pueden crear múltiples instancias (objetos) de una clase, y cada objeto tendrá
su propio conjunto de atributos y podrá ejecutar los métodos definidos en la clase.
Ejemplo. Una tarjeta de crédito puede representarse como un objeto:
• Atributos: Número de la tarjeta, titular, balance, fecha de caducidad, pin, entidad
emisora, estado (activa o no), etc.
• Métodos: Activar, pagar, renovar, anular.
1
Conceptos Clave de la POO en Python
Python implementa la POO a través de varios conceptos clave que forman la base general
de este paradigma:
• Clases: Las clases son los planos o moldes para crear objetos. Definen un conjunto
de atributos (datos) y métodos (funciones) que caracterizan a cualquier objeto de
ese tipo.
• Objetos: Un objeto es una instancia de una clase. Cada objeto tiene un estado
definido por sus atributos y comportamiento determinado por sus métodos. Los
objetos son los actores fundamentales en programas orientados a objetos.
• Herencia: La herencia permite crear nuevas clases que reutilizan, extienden o
modifican el comportamiento de las clases existentes. Facilita la creación de
jerarquías de clases y promueve la reutilización de código.
• Polimorfismo: El polimorfismo se refiere a la capacidad de utilizar una interfaz
única para diferentes tipos de datos o clases. En Python, permite que funciones o
métodos puedan procesar objetos de diferentes clases que comparten la misma
interfaz.
• Encapsulación: Este principio oculta los detalles internos de cómo una clase
implementa sus características, exponiendo solo lo que es necesario para el uso de
la clase. La encapsulación protege los datos de un objeto contra acceso no
autorizado y facilita la modificación del comportamiento interno sin afectar a quienes
usan la clase.
Definición y uso de clases y objetos en Python
En Python, las clases y los objetos son los pilares fundamentales de la Programación
Orientada a Objetos (POO).
• Una clase actúa como un plano para la creación de objetos, definiendo los
atributos (datos) y métodos (funciones) que los objetos creados a partir de la clase
podrán utilizar.
• Los objetos son instancias de estas clases; cada objeto puede tener atributos
distintos definidos en la clase, permitiendo a los desarrolladores modelar entidades
del mundo real de manera efectiva y eficiente.
Creación de Clases
Para definir una clase en Python, se utiliza la palabra clave class, seguida del nombre de
la clase y dos puntos. Dentro de la clase, se definen funciones que actúan como métodos
para los objetos de la clase. Un método especial, __init__(), se utiliza como constructor
para inicializar los atributos del objeto cuando se crea una instancia de la clase.
class Persona:
def __init__(self, nombre, edad):
[Link] = nombre
[Link] = edad
def saludar(self):
print(f'Hola, mi nombre es {[Link]} y tengo {[Link]} años.')
2
¿Qué es un Constructor?
Un constructor es un método especial que se invoca automáticamente cuando se instancia
una clase. Su principal función es inicializar los atributos de la clase con valores
predeterminados o proporcionados. En Python, el constructor se implementa con el método
__init__(), que se llama inmediatamente después de que se crea un nuevo objeto.
Parámetro SELF
En Python siempre los métodos ubicados dentro de una clase comienzan con un
parámetro llamado self y luego los parámetros de inicialización.
Se puede llamar de otro nombre si se desea, pero por convención siempre se emplea la
palabra self.
self (a si mismo), es una variable útil para acceder a las variables del propio objeto.
El constructor liga todas las variables con el atributo self
Métodos Mágicos en Python y su uso en las Clases
En programación orientada a objetos, los métodos mágicos son funciones especiales que
permiten definir comportamientos específicos para las clases.
Estos métodos se llaman “mágicos” porque su nombre comienza y termina con dos
guiones bajos (__).
Por ejemplo, el método __init__ se utiliza para inicializar objetos y es invocado
automáticamente cuando se crea una instancia de la clase.
Otro ejemplo popular es el método __str__, que se utiliza para representar el objeto en
forma de cadena de texto y permite que se pueda imprimir en la consola de forma legible.
Un ejemplo sencillo para ilustrar su uso es el siguiente:
class Persona:
def __init__(self, nombre):
[Link] = nombre
def __str__(self):
return f"Mi nombre es {[Link]}"
persona1 = Persona("Juan")
print(persona1)
En este caso, al crear una instancia de la clase Persona se llama automáticamente al
método __init__ para asignar el nombre del objeto. Posteriormente, al imprimir el objeto
utilizando print(persona1), se llama automáticamente al método __str__ que retorna una
representación en texto de la instancia.
3
Instanciación de Objetos
Crear un objeto a partir de una clase se conoce como instanciación. Esto se hace llamando
al nombre de la clase como si fuera una función, pasando los argumentos requeridos por el
método __init__.
persona1 = Persona('Ana', 30)
[Link]() # Salida: Hola, mi nombre es Ana y tengo 30 años.
Mientras que la clase es un molde, a los objetos creados se les conoce como instancias.
Uso de Atributos y Métodos
Una vez que se ha creado un objeto, se puede acceder a sus atributos y métodos
utilizando la notación de punto. Esto permite modificar los atributos del objeto y llamar a
sus métodos, respectivamente.
# Accediendo a un atributo
print([Link]) # Salida: Ana
print([Link])
# Llamando a un método
[Link]()
Código completo:
class Persona:
def __init__(self, nombre, edad):
[Link] = nombre
[Link] = edad
def saludar(self):
print(f'Hola, mi nombre es {[Link]} y tengo {[Link]} años.')
persona1 = Persona('Ana', 30)
[Link]() # Salida: Hola, mi nombre es Ana y tengo 30 años.
# Accediendo a un atributo
print([Link]) # Salida: Ana
4
print([Link])
# Llamando a un método
[Link]()
Atributos y métodos en Python
En la Programación Orientada a Objetos (POO) con Python, los atributos y métodos son
componentes esenciales de las clases, proporcionando la estructura y el comportamiento
que los objetos de esas clases tendrán. A continuación, se detalla cómo se definen y
utilizan dentro del paradigma de POO.
Definición de Atributos
Los atributos son variables que se asocian con una clase. Almacenan datos que son
importantes para los objetos creados a partir de esa clase. Los atributos se definen dentro
del método constructor __init__ de la clase, utilizando el prefijo self para indicar que
pertenecen a instancias de la clase.
class Coche:
def __init__(self, marca, modelo, año):
[Link] = marca
[Link] = modelo
self.año = año
Definición de Métodos
Los métodos son funciones que se definen dentro de una clase y están diseñados para
operar en los datos (atributos) que los objetos de la clase contienen. Al igual que los
atributos, se utilizan con el prefijo self para acceder a las variables y otros métodos del
objeto.
class Coche:
def __init__(self, marca, modelo, año):
[Link] = marca
[Link] = modelo
self.año = año
def descripcion(self):
return f'{[Link]} {[Link]} de {self.año}'
def es_antiguo(self):
return 2025 - self.año > 20
5
Creación de Clases con Atributos y Métodos
Para utilizar estas definiciones, primero se crea una instancia de la clase y luego se accede
a sus atributos y métodos utilizando la notación de punto. Esto permite no solo almacenar
datos específicos en cada objeto sino también realizar operaciones o acciones específicas
definidas por los métodos.
mi_coche = Coche('Toyota', 'Corolla', 1999)
print(mi_coche.descripcion()) # Salida: Toyota Corolla de 1999
print(mi_coche.es_antiguo()) # Salida: True
Código completo:
class Coche:
def __init__(self, marca, modelo, año):
[Link] = marca
[Link] = modelo
self.año = año
def descripcion(self):
return f'{[Link]} {[Link]} de {self.año}'
def es_antiguo(self):
return 2023 - self.año > 20
mi_coche = Coche('Toyota', 'Corolla', 1999)
print(mi_coche.descripcion()) # Salida: Toyota Corolla de 1999
print(mi_coche.es_antiguo()) # Salida: True
La combinación de atributos y métodos en las clases proporciona una manera de modelar
entidades del mundo real, permitiendo que el código sea más organizado, reutilizable y
fácil de mantener.
Al encapsular datos y funcionalidades específicas dentro de objetos, Python facilita el
desarrollo de software complejo, haciéndolo más accesible y manejable.
Principios básicos de la POO
La Programación Orientada a Objetos (POO) en Python se fundamenta en cuatro
principios básicos que juntos facilitan el diseño de software robusto, escalable y fácil de
mantener.
Encapsulación
La encapsulación se refiere a la práctica de ocultar los detalles internos de la
implementación de un objeto y exponer solo aquellos componentes que sean seguros y
necesarios para el uso externo.
Esto se logra a través del uso de métodos (funciones dentro de clases) que actúan como
interfaz pública de un objeto. La encapsulación mejora la seguridad y la modularidad del
6
código, permitiendo que los cambios internos se realicen sin afectar otras partes del
programa.
class CuentaBancaria:
def __init__(self, saldo):
self._saldo = saldo # Atributo privado
def depositar(self, cantidad):
# Lógica para depositar dinero
self._saldo += cantidad
def retirar(self, cantidad):
# Lógica para retirar dinero
self._saldo -= cantidad
def obtener_saldo(self):
return self._saldo
# Creación de un objeto basado en la clase CuentaBancaria
cuenta = CuentaBancaria(1000)
[Link](500)
[Link](200)
print(F"El saldo de la cuenta es: {cuenta.obtener_saldo()}") # Imprime: 1300
En este ejemplo, la clase “CuentaBancaria” encapsula el saldo como un atributo privado
[_saldo ]. Los métodos [ ( depositar(), retirar() y obtener_saldo() ] proporcionan una interfaz
para interactuar con el saldo sin acceder directamente al atributo privado.
Hay ciertos métodos o atributos que queremos que pertenezcan sólo a la clase o al objeto,
y que sólo puedan ser accedidos por los mismos. Para ello podemos usar el subrayado
simple (_) o doble (__), para nombrar a un atributo o método. Esto hará que Python los
interprete como “privados”, de manera que no podrán ser accedidos desde el exterior.
Abstracción
La abstracción implica enfocarse en las características esenciales de un objeto, ignorando
detalles irrelevantes o accidentales.
En la POO, las clases proporcionan una forma de abstraer objetos del mundo real,
definiendo sus atributos esenciales y comportamientos. La abstracción ayuda a reducir la
complejidad del diseño, permitiendo a los desarrolladores concentrarse en interacciones a
alto nivel entre objetos.
class Empleado:
def __init__(self, nombre, salario):
[Link] = nombre
[Link] = salario
print(F"{[Link]}, {[Link]}")
def calcular_salario(self):
# Cálculo del salario
pass
def imprimir_informacion(self):
# Impresión de información del empleado
7
pass
# Creación de objetos basados en la clase Empleado
empleado1 = Empleado("Juan", 2500)
empleado2 = Empleado("María", 3000)
En este ejemplo, la clase “Empleado” abstrae las características comunes de los
empleados, como el nombre y el salario. Los métodos [ calcular_salario() e
imprimir_informacion() ] representan comportamientos específicos relacionados con los
empleados.
Herencia
La herencia es un mecanismo que permite a una nueva clase heredar atributos y métodos
de una clase existente.
La clase original se conoce como la clase base o superclase, mientras que la nueva clase
se denomina subclase. La herencia promueve la reutilización de código y establece una
relación jerárquica entre clases, facilitando la creación de estructuras de objetos complejas.
class Vehiculo:
def __init__(self, marca, modelo):
[Link] = marca
[Link] = modelo
def conducir(self):
print("El vehículo está en movimiento.")
class Coche(Vehiculo):
def __init__(self, marca, modelo, color):
[Link] = color
def estacionar(self):
print("El coche está estacionado.")
class Motocicleta(Vehiculo):
def __init__(self, marca, modelo, cilindrada):
[Link] = cilindrada
def hacer_acrobacias(self):
print("La motocicleta está haciendo acrobacias.")
# Creación de objetos basados en las clases derivadas
coche = Coche("Ford", "Focus", "Rojo")
[Link]()
motocicleta = Motocicleta("Honda", "CBR", 600)
[Link]()
motocicleta.hacer_acrobacias()
8
En este ejemplo, la clase “Vehículo” es la clase base que tiene los atributos y
comportamientos comunes a todos los vehículos. Las clases “Coche” y “Motocicleta”
heredan de la clase “Vehiculo” y agregan sus propios atributos
Polimorfismo
El polimorfismo permite que objetos de diferentes clases sean tratados como instancias de
una clase común si comparten la misma interfaz (es decir, un conjunto de métodos
públicos).
Esto significa que una función puede utilizar objetos de diferentes clases si todos ellos
implementan un método específico. El polimorfismo aumenta la flexibilidad y la
interoperabilidad del código, permitiendo diseñar sistemas más genéricos y extensibles.
class Vehiculo:
def hacer_ruido(self):
pass # Método que será sobreescrito en las clases derivadas
class Coche(Vehiculo):
def hacer_ruido(self):
return "El Coche hace Vroom"
class Motocicleta(Vehiculo):
def hacer_ruido(self):
return "La Motocicleta hace Brrrm"
# Función que utiliza polimorfismo
def imprimir_ruido(vehiculo):
print(vehiculo.hacer_ruido())
# Creación de objetos
coche = Coche()
motocicleta = Motocicleta()
# Uso de la función con diferentes tipos de vehículos
imprimir_ruido(coche) # Imprime: Vroom
imprimir_ruido(motocicleta) # Imprime: Brrrm
Explicación:
1. Clase Vehiculo: Clase base que define el método hacer_ruido sin implementación.
2. Clases Coche y Motocicleta: Heredan de Vehiculo y sobreescriben el método
hacer_ruido para proporcionar sus propias implementaciones.
3. Función imprimir_ruido: Acepta un objeto de tipo Vehiculo y llama al método
hacer_ruido. Gracias al polimorfismo, se ejecutará el método correcto según el tipo
de vehículo que se pase (ya sea un Coche o una Motocicleta).
Este ejemplo ilustra cómo diferentes tipos de vehículos pueden tener su propio
comportamiento al hacer ruido, utilizando la misma interfaz.
9
Ejercicios:
Ejercicio 1
Crea una clase “Persona”. Con atributos nombre y edad. Además, crea un método
“cumpleaños”, que aumente en 1 la edad de la persona cuando se invoque sobre un objeto
creado con “Persona”.
class persona:
def __init__(self, nombre, edad):
[Link]=nombre
[Link]=edad
def cumpleaños(self):
[Link] += 1
nombre=input("Ingrese nombre del estudiante: ")
edad=int(input("Ingrese edad del estudiante: "))
persona1=persona(nombre, edad)
[Link]ños()
print(f"Felicidades, Sr(ta) {[Link]} hoy cumples {[Link]} años")
Ejercicio 2
Calcula el volumen y el área de la base de un cilindro.
Área de la base = π × r2
Volumen = π × r2 × h
import math
class Cilindro:
#Constructor
def __init__(self, radio, height, color):
[Link] = radio
[Link] = height
[Link] = color
#Método de Instancia
def area_base(self):
return 3.1416 * [Link] ** 2
#Método de Instancia
def volumen(self):
return [Link] * [Link] ** 2 * [Link]
cilindro1 = Cilindro(2, 3, 'red')
print(f'El área de la base del cilindro es {cilindro1.area_base()}')
print(f'El volumen del cilindro es {[Link]()}')
#Cambiando algún atributo de la clase
[Link] = 1.5
10
print(f'El área de la base del cilindro es {cilindro1.area_base():.2f}')
print(f'El volumen del cilindro es {[Link]():.2f}')
Ejercicio 3
Realizar un programa que conste de una clase llamada Estudiante, 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. Pida
por teclado, el nombre y la nota del estudiante.
class Estudiante():
def __init__(self, nombre, nota):
[Link]=nombre
[Link]=nota
def imprimir(self):
print(f"Nombre:{[Link]} \nNota: {[Link]}")
def resultados(self):
if [Link] >= 7:
print("Has APROBADO!")
else:
print("Has REPROBADO!")
nombre=input("Ingrese nombre del Estudiante: ")
nota=float(input("Ingrese la nota del estudiante: "))
estudiante1=Estudiante(nombre, nota)
[Link]()
[Link]()
Ejercicio 4
Crear una clase Fabrica que tenga los atributos de Llantas, Color y Precio; luego crear dos
clases más que hereden de Fabrica, las cuales son Moto y Carro.
Crear métodos que muestren la cantidad de llantas, color y precio de ambos transportes.
Por último, crear objetos para cada clase y mostrar por pantalla los atributos de cada uno.
class Fabrica():
def __init__(self, llantas, color, precio):
[Link]=llantas
[Link]=color
[Link]=precio
class Moto(Fabrica):
def caracteristicas(self):
print("El OBJETO es una moto")
print(f"Cantidad de llantas: {[Link]}\nEl color es: {[Link]}\nEl precio es: {[Link]}")
class Carro(Fabrica):
def caracteristicas(self):
print("El OBJETO es un carro")
print(f"Cantidad de llantas: {[Link]}\nEl color es: {[Link]}\nEl precio es: {[Link]}")
moto=Moto(2, "Gris", "$6,000")
[Link]()
print()
carro=Carro(4 ,"Plata", "$15,000")
11
[Link]()
Ejercicio 5
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.
class Calculadora():
def __init__(self, num1, num2):
self.num1=num1
self.num2=num2
def suma(self):
resultado=self.num1 + self.num2
print(f"El resultado de la suma es: {self.num1} + {self.num2} = {resultado}")
def resta(self):
resultado=self.num1 - self.num2
print(f"El resultado de la resta es: {self.num1} – {self.num2} = {resultado}")
def division(self):
resultado=self.num1 // self.num2
print(f"El resultado de la divisón es: {self.num1} // {self.num2} = {resultado}")
def multiplicacion(self):
resultado=self.num1 * self.num2
print(f"El resultado de la multiplicación es: {self.num1} * {self.num2} = {resultado}")
operacion=Calculadora(10, 5)
[Link]()
operacion=Calculadora(20, 5)
[Link]()
operacion=Calculadora(15, 3)
[Link]()
operacion=Calculadora(8, 4)
[Link]()
12
Ejercicio 6
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).
# creamos nuestra clase
class Triangulo:
def __init__(self,lado1,lado2,lado3):
self.lado1=lado1
self.lado2=lado2
self.lado3=lado3
# imprimimos
def imprimir(self):
print("Los lados del triángulo tienen el valor de")
print("Lado 1: ",self.lado1)
print("Lado 2: ",self.lado2)
print("Lado 3: ",self.lado3)
# comprobamos el lado mayor
def mayor(self):
if self.lado1>self.lado2 and self.lado1>self.lado3:
print("El lado Mayor es el 1: ",self.lado1)
elif self.lado2>self.lado3:
print("El lado Mayor es el 2: ",self.lado2)
else:
print("El lado Mayor es el 3: ",self.lado3)
# comprobamos el tipo de triángulo
# equilátero -> todos los lados iguales
# isósceles -> dos lados iguales
# escaleno -> todos los lados desiguales
def tipo(self):
if self.lado1==self.lado2 and self.lado1==self.lado3:
print("Es un triángulo equilátero")
elif self.lado1!=self.lado2 and self.lado1!=self.lado3:
print("Es un triángulo escaleno")
else:
print("Es un triángulo isósceles")
# bloque principal
lado1=int(input("Ingrese el valor del primer lado: "))
lado2=int(input("Ingrese el valor del segundo lado: "))
lado3=int(input("Ingrese el valor del tercer lado: "))
13
figura=Triangulo(lado1,lado2,lado3)
[Link]()
[Link]()
[Link]()
14