Fundamentos
Tutorial Fundamentos: Concepto de clases y objetos
Python y la POO: Aprende a definir clases, crear objetos y aplicar encapsulación con la última versión de Python. Ideal para principiantes.
Aprende Fundamentos GRATIS y certifícateDefinición de clase: atributos y métodos
En la programación orientada a objetos (POO), una clase es una estructura que permite definir un tipo de dato abstracto que combina datos y comportamientos. Una clase actúa como un molde a partir del cual se pueden crear instancias concretas denominadas objetos.
Los atributos son las características o propiedades que describen el estado de los objetos. Representan los datos que cada instancia de la clase mantendrá. Por ejemplo, en una clase Coche
, los atributos podrían ser marca
, modelo
y color
. Estos atributos se definen dentro de la clase y cada objeto tendrá sus propios valores para ellos.
Los métodos son las acciones o comportamientos que los objetos pueden realizar. Son funciones definidas dentro de la clase que operan sobre los atributos o realizan operaciones específicas. Siguiendo el ejemplo anterior, la clase Coche
podría tener métodos como acelerar()
, frenar()
o girar(angulo)
.
A continuación, se muestra cómo definir una clase en Python con atributos y métodos:
class Coche:
def __init__(self, marca, modelo, color):
self.marca = marca # Atributo marca
self.modelo = modelo # Atributo modelo
self.color = color # Atributo color
def acelerar(self):
print(f"El {self.marca} {self.modelo} está acelerando.") # Método acelerar
def frenar(self):
print(f"El {self.marca} {self.modelo} está frenando.") # Método frenar
En este ejemplo, la clase Coche
tiene un método especial __init__
, conocido como constructor, que se utiliza para inicializar los atributos cuando se crea un nuevo objeto. Los parámetros marca
, modelo
y color
se asignan a los atributos del objeto utilizando self
, que hace referencia a la instancia actual de la clase.
Los métodos de instancia, como acelerar
y frenar
, permiten que los objetos realizados acciones utilizando sus propios atributos. Al invocar estos métodos, el objeto utiliza su estado interno para ejecutar las operaciones definidas.
Es posible definir atributos de clase, que son compartidos por todas las instancias. Por ejemplo:
class Coche:
numero_ruedas = 4 # Atributo de clase compartido por todos los coches
def __init__(self, marca, modelo, color):
self.marca = marca
self.modelo = modelo
self.color = color
Aquí, numero_ruedas
es un atributo común a todos los objetos de la clase Coche
. Esto es útil para definir propiedades que son iguales para todas las instancias.
Los métodos de clase y los métodos estáticos son otros tipos de métodos que no operan sobre instancias individuales. Un método de clase recibe la clase como primer argumento y se define con el decorador @classmethod
, mientras que un método estático no recibe ningún argumento especial y se define con @staticmethod
:
class Coche:
numero_ruedas = 4
@classmethod
def get_numero_ruedas(cls):
return cls.numero_ruedas # Método de clase que accede al atributo de clase
@staticmethod
def velocidad_maxima():
return 240 # Método estático que devuelve un valor fijo
Los atributos y métodos pueden tener diferentes niveles de acceso. Para indicar que un atributo o método es privado, se utiliza una convención de nomenclatura con dos guiones bajos (__
). Por ejemplo:
class CuentaBancaria:
def __init__(self, titular, saldo):
self.titular = titular
self.__saldo = saldo # Atributo privado
def depositar(self, cantidad):
self.__saldo += cantidad # Método que modifica un atributo privado
def __actualizar_saldo(self):
pass # Método privado
def obtener_saldo(self):
return self.__saldo # Método público que accede a un atributo privado
En este caso, __saldo
es un atributo privado y __actualizar_saldo()
es un método privado. Esto implementa el principio de encapsulación, protegiendo el estado interno de la clase y controlando cómo se accede o modifica.
La definición clara y estructurada de clases, atributos y métodos es esencial para crear programas organizados y facilitate el mantenimiento del código. Permite modelar entidades complejas del mundo real de manera lógica y coherente, aprovechando las ventajas que ofrece la programación orientada a objetos.
Instanciación de objetos: creación y uso
Tras definir una clase, el siguiente paso es crear objetos concretos que representen instancias de esa clase. La instanciación es el proceso mediante el cual se crea un nuevo objeto utilizando el constructor de una clase, lo que permite trabajar con datos y comportamientos específicos.
Para instanciar un objeto en Python, se utiliza la sintaxis nombre_de_clase(parámetros)
. Esto llama al método __init__
de la clase y devuelve una nueva instancia. Por ejemplo, si disponemos de la clase Coche
:
class Coche:
def __init__(self, marca, modelo, color):
self.marca = marca
self.modelo = modelo
self.color = color
def acelerar(self):
print(f"El {self.marca} {self.modelo} está acelerando.")
def frenar(self):
print(f"El {self.marca} {self.modelo} está frenando.")
Podemos crear una instancia de Coche
de la siguiente manera:
mi_coche = Coche("Renault", "Clio", "Blanco")
Aquí, mi_coche
es un objeto de la clase Coche
con los atributos marca
, modelo
y color
inicializados. Podemos acceder a sus atributos utilizando la notación de punto:
print(mi_coche.marca) # Imprime: Renault
print(mi_coche.modelo) # Imprime: Clio
print(mi_coche.color) # Imprime: Blanco
También es posible invocar sus métodos de la misma manera:
mi_coche.acelerar() # Salida: El Renault Clio está acelerando.
mi_coche.frenar() # Salida: El Renault Clio está frenando.
La instanciación permite crear múltiples objetos con diferentes estados. Por ejemplo:
coche_de_ana = Coche("Peugeot", "208", "Rojo")
coche_de_luis = Coche("Volkswagen", "Golf", "Negro")
print(coche_de_ana.marca) # Imprime: Peugeot
print(coche_de_luis.color) # Imprime: Negro
Cada instancia de Coche
mantiene sus propios valores de atributos, lo que refleja la independencia entre los objetos creados a partir de la misma clase.
Es posible modificar los atributos de un objeto después de su creación:
mi_coche.color = "Azul"
print(mi_coche.color) # Imprime: Azul
Sin embargo, es recomendable controlar el acceso a los atributos mediante métodos específicos para mantener la integridad de los datos, siguiendo los principios de la encapsulación.
La creación y uso de objetos también facilita la organización y manipulación de conjuntos de datos. Por ejemplo, podemos almacenar objetos en una lista:
flota = [mi_coche, coche_de_ana, coche_de_luis]
for coche in flota:
coche.acelerar()
Este código recorrerá cada objeto en la lista flota
y llamará al método acelerar()
de cada uno, demostrando cómo los objetos pueden ser manejados de forma colectiva.
Además, podemos pasar objetos como argumentos a funciones o métodos:
def mostrar_informacion(coche):
print(f"Marca: {coche.marca}, Modelo: {coche.modelo}, Color: {coche.color}")
mostrar_informacion(mi_coche)
La instanciación de objetos es esencial para aprovechar las ventajas de la programación orientada a objetos, permitiendo modelar entidades reales y crear aplicaciones más modulables y mantenibles. Al utilizar objetos, se puede encapsular la complejidad y trabajar con abstracciones que representan conceptos del mundo real.
Es importante entender que mientras la clase define la estructura y comportamiento general, los objetos son instancias concretas con datos específicos. Esto permite crear programas flexibles y adaptables a diferentes contextos y necesidades.
Diferencia entre clases y objetos en la práctica
En la programación orientada a objetos, es fundamental entender la distinción entre una clase y un objeto para aplicar correctamente los conceptos y diseñar programas eficientes. Aunque las clases y los objetos están estrechamente relacionados, cumplen roles diferentes en la estructura del código y su ejecución.
Una clase es una plantilla o modelo que define las propiedades y comportamientos que tendrán sus objetos. Es una abstracción que encapsula datos y funciones, sin ocupar espacio en memoria hasta que se crean instancias de ella. Por otro lado, un objeto es una instancia concreta de una clase, que ocupa espacio en memoria y posee valores específicos en sus atributos.
Para ilustrar la diferencia en la práctica, consideremos el proceso de desarrollo de una aplicación de gestión de biblioteca. Se puede definir una clase Libro
que describa las características generales de los libros:
class Libro:
def __init__(self, titulo, autor, isbn):
self.titulo = titulo
self.autor = autor
self.isbn = isbn
def mostrar_informacion(self):
print(f"'{self.titulo}' por {self.autor} (ISBN: {self.isbn})")
La clase Libro
actúa como un molde que especifica qué atributos (titulo
, autor
, isbn
) y métodos (mostrar_informacion
) tendrán los libros. No representa ningún libro en particular hasta que se crean objetos a partir de ella.
Al crear objetos de la clase Libro
, se generan instancias únicas con datos específicos:
libro1 = Libro("Cien años de soledad", "Gabriel García Márquez", "978-0307474728")
libro2 = Libro("Don Quijote de la Mancha", "Miguel de Cervantes", "978-8491050294")
Aquí, libro1
y libro2
son objetos diferentes, cada uno con sus propios valores en los atributos. Aunque comparten la misma estructura definida por la clase Libro
, son entidades independientes en memoria.
En la práctica, la clase es utilizada por los desarrolladores para definir la estructura y el comportamiento común de un conjunto de objetos. Los objetos, en cambio, son manipulados en tiempo de ejecución, almacenan los datos y permiten la interacción con el usuario o con otros componentes del programa.
Es importante destacar que las clases pueden contener lógica compleja, métodos estáticos y atributos de clase, pero no representan elementos activos hasta que se instancian. Los objetos son los que interactúan durante la ejecución, permitiendo que el programa realice tareas concretas.
Otro ejemplo práctico es en el desarrollo de un juego. Se puede tener una clase Personaje
que defina propiedades comunes a todos los personajes:
class Personaje:
num_personajes = 0 # Atributo de clase
def __init__(self, nombre, salud):
self.nombre = nombre
self.salud = salud
Personaje.num_personajes += 1 # Acceso a atributo de clase
def atacar(self, otro_personaje):
print(f"{self.nombre} ataca a {otro_personaje.nombre}.")
@classmethod
def mostrar_total_personajes(cls):
print(f"Total de personajes: {cls.num_personajes}")
La clase Personaje
define la estructura para todos los personajes del juego, pero no existe ningún personaje específico hasta que se crean objetos:
hero = Personaje("Aragorn", 100)
villano = Personaje("Sauron", 150)
Los objetos hero
y villano
representan entidades individuales en el juego, con estados particulares que pueden cambiar a lo largo de la ejecución. El método mostrar_total_personajes
es un ejemplo de cómo las clases pueden mantener y proporcionar información general sin referirse a una instancia concreta.
En términos prácticos, se trabaja con clases cuando se diseña y estructura el código, definiendo las relaciones y comportamientos genéricos. Se interactúa con objetos cuando se ejecuta el programa, manipulando datos específicos y realizando operaciones concretas.
Algunas diferencias clave en la práctica son:
- Definición vs. instanciación: Las clases se definen una sola vez en el código, mientras que los objetos se pueden instanciar múltiples veces durante la ejecución.
- Espacio en memoria: Las clases no ocupan espacio significativo en memoria hasta que se crean objetos; los objetos sí ocupan espacio, ya que almacenan datos.
- Métodos y atributos: Las clases contienen la definición de métodos y atributos, pero los objetos tienen los valores concretos de esos atributos y ejecutan los métodos con su propio estado.
- Uso: Se accede a los atributos y métodos de una clase a través de los objetos o, en el caso de atributos y métodos de clase, directamente desde la clase.
Por ejemplo, para acceder a un método de instancia:
hero.atacar(villano) # El objeto hero realiza la acción atacar
Para acceder a un método de clase:
Personaje.mostrar_total_personajes() # Se accede al método desde la clase
Entender esta distinción es esencial para aprovechar al máximo las capacidades de la programación orientada a objetos. Permite separar la lógica general (clases) de los datos específicos (objetos), facilitando la reutilización de código y el mantenimiento de aplicaciones complejas.
En resumen, mientras que la clase es una abstracción que describe qué es y qué puede hacer un objeto, el objeto es la realización concreta de esa descripción, con la que se interactúa directamente en el programa. Esta diferencia es fundamental para el diseño de software modular y escalable.
Ejemplos prácticos: modelado de entidades del mundo real
Para comprender cómo aplicar la programación orientada a objetos en problemas reales, es útil modelar entidades del mundo real como clases y objetos. A continuación, se presentan ejemplos prácticos que demuestran cómo traducir conceptos cotidianos en código.
Ejemplo 1: Modelo de un estudiante
Supongamos que queremos crear un sistema para gestionar la información de estudiantes en una universidad. Podemos definir una clase Estudiante
con atributos y métodos relevantes.
class Estudiante:
def __init__(self, nombre, edad, carrera):
self.nombre = nombre # Atributo nombre
self.edad = edad # Atributo edad
self.carrera = carrera # Atributo carrera
self.notas = [] # Atributo notas inicializado como lista vacía
def agregar_nota(self, nota):
self.notas.append(nota) # Método para agregar una nota
def calcular_promedio(self):
if self.notas:
return sum(self.notas) / len(self.notas) # Método para calcular el promedio
else:
return 0
def mostrar_informacion(self):
print(f"Nombre: {self.nombre}")
print(f"Edad: {self.edad}")
print(f"Carrera: {self.carrera}")
print(f"Promedio: {self.calcular_promedio():.2f}")
En este ejemplo, la clase Estudiante
modela la entidad real de un estudiante. Los atributos nombre
, edad
y carrera
almacenan la información personal, mientras que notas
es una lista que guarda las calificaciones. Los métodos agregar_nota
, calcular_promedio
y mostrar_informacion
permiten manipular y mostrar los datos del estudiante.
Podemos crear instancias de Estudiante
y utilizarlas en nuestro programa:
estudiante1 = Estudiante("María García", 20, "Ingeniería Informática")
estudiante1.agregar_nota(85)
estudiante1.agregar_nota(90)
estudiante1.agregar_nota(78)
estudiante1.mostrar_informacion()
La salida será:
Nombre: María García
Edad: 20
Carrera: Ingeniería Informática
Promedio: 84.33
Ejemplo 2: Sistema de gestión de productos
Consideremos ahora el modelado de productos en una tienda. Podemos definir una clase Producto
que represente los artículos disponibles.
class Producto:
def __init__(self, codigo, nombre, precio, stock):
self.codigo = codigo # Atributo código de producto
self.nombre = nombre # Atributo nombre del producto
self.precio = precio # Atributo precio
self.stock = stock # Atributo stock disponible
def vender(self, cantidad):
if self.stock >= cantidad:
self.stock -= cantidad
print(f"Se han vendido {cantidad} unidades de {self.nombre}.")
else:
print(f"No hay suficiente stock de {self.nombre}.")
def reponer(self, cantidad):
self.stock += cantidad
print(f"Se han agregado {cantidad} unidades al stock de {self.nombre}.")
def mostrar_informacion(self):
print(f"Código: {self.codigo}")
print(f"Producto: {self.nombre}")
print(f"Precio: {self.precio}€")
print(f"Stock: {self.stock}")
La clase Producto
representa un artículo con sus atributos y métodos para gestionar el inventario. Podemos instanciar y utilizar esta clase en un sistema de ventas:
producto1 = Producto("P001", "Camiseta", 19.99, 50)
producto1.mostrar_informacion()
producto1.vender(5)
producto1.mostrar_informacion()
producto1.reponer(10)
producto1.mostrar_informacion()
Este código gestionará las operaciones sobre el producto, actualizando el stock y mostrando la información actualizada.
Ejemplo 3: Gestión de una cuenta bancaria
Otro ejemplo es el modelado de una cuenta bancaria. Definimos una clase CuentaBancaria
que permite operaciones básicas.
class CuentaBancaria:
def __init__(self, numero_cuenta, titular, saldo=0):
self.numero_cuenta = numero_cuenta # Atributo número de cuenta
self.titular = titular # Atributo titular de la cuenta
self.__saldo = saldo # Atributo privado saldo
def depositar(self, cantidad):
self.__saldo += cantidad
print(f"Se han depositado {cantidad}€. Nuevo saldo: {self.__saldo}€.")
def retirar(self, cantidad):
if self.__saldo >= cantidad:
self.__saldo -= cantidad
print(f"Se han retirado {cantidad}€. Nuevo saldo: {self.__saldo}€.")
else:
print("Saldo insuficiente.")
def consultar_saldo(self):
print(f"El saldo actual es: {self.__saldo}€.")
En esta clase, el atributo __saldo
es privado para proteger la información financiera. Los métodos permiten realizar depósitos, retiros y consultar el saldo. Ejemplo de uso:
cuenta1 = CuentaBancaria("ES1234567890", "Juan Pérez", 1000)
cuenta1.consultar_saldo()
cuenta1.depositar(500)
cuenta1.retirar(200)
cuenta1.consultar_saldo()
Este código simula operaciones bancarias básicas, respetando la encapsulación de datos sensibles.
Integración de objetos
Además de crear clases individuales, es común que los objetos interactúen entre sí. Por ejemplo, un sistema de gestión de pedidos donde un Cliente
realiza un Pedido
que contiene varios Productos.
Definimos una clase Cliente
y una clase Pedido
:
class Cliente:
def __init__(self, nombre, direccion, telefono):
self.nombre = nombre # Atributo nombre
self.direccion = direccion # Atributo dirección
self.telefono = telefono # Atributo teléfono
def mostrar_informacion(self):
print(f"Cliente: {self.nombre}")
print(f"Dirección: {self.direccion}")
print(f"Teléfono: {self.telefono}")
class Pedido:
def __init__(self, cliente):
self.cliente = cliente # Atributo cliente asociado al pedido
self.productos = [] # Lista de productos en el pedido
def agregar_producto(self, producto, cantidad):
self.productos.append((producto, cantidad)) # Añade una tupla de producto y cantidad
def mostrar_pedido(self):
self.cliente.mostrar_informacion()
print("Productos del pedido:")
total = 0
for producto, cantidad in self.productos:
subtotal = producto.precio * cantidad
print(f"- {producto.nombre} x {cantidad} unidades: {subtotal}€")
total += subtotal
print(f"Total a pagar: {total}€")
Con estas clases, podemos simular la realización de un pedido:
cliente1 = Cliente("Ana López", "Calle Mayor 10", "600123456")
producto1 = Producto("P001", "Camiseta", 19.99, 50)
producto2 = Producto("P002", "Pantalón", 39.99, 30)
pedido1 = Pedido(cliente1)
pedido1.agregar_producto(producto1, 2)
pedido1.agregar_producto(producto2, 1)
pedido1.mostrar_pedido()
Esta interacción entre objetos refleja situaciones reales donde diferentes entidades colaboran. El pedido incluye productos y está asociado a un cliente, demostrando la capacidad de los objetos para modelar sistemas complejos.
Todas las lecciones de Fundamentos
Accede a todas las lecciones de Fundamentos y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
¿Qué Es La Programación?
Introducción Y Entorno
Lenguajes De Programación
Introducción Y Entorno
Ciclo De Vida Del Desarrollo De Software
Introducción Y Entorno
Herramientas Y Entornos De Desarrollo
Introducción Y Entorno
Instalar Y Configurar Pseint Y Python
Introducción Y Entorno
Estructura De Un Programa Pseint
Introducción Y Entorno
Pensamiento Algorítmico
Lógica
Tipos De Datos Y Variables
Lógica
Operadores
Lógica
Estructuras De Control Condicional
Lógica
Estructuras De Control De Repetición
Lógica
Diagramas De Flujo
Lógica
Depuración De Programas
Lógica
Arrays
Estructuras De Datos
Matrices
Estructuras De Datos
Cadenas De Caracteres
Estructuras De Datos
Algoritmos De Ordenamiento
Ordenamiento Y Búsqueda
Algoritmos De Búsqueda
Ordenamiento Y Búsqueda
Complejidad Temporal Y Espacial
Ordenamiento Y Búsqueda
Definición Y Utilidad De Las Funciones
Funciones
Paso De Parámetros
Funciones
Recursividad
Funciones
Funciones Anónimas
Funciones
Concepto De Clases Y Objetos
Programación Orientada A Objetos
Método Constructor
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Composición
Programación Orientada A Objetos
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el concepto de clases, atributos y métodos.
- Aprender la sintaxis de definición de clases en Python.
- Captar la distinción entre clases y objetos.
- Entender la encapsulación y el acceso a atributos privados.
- Crear y manipular instancias de objetos.
- Aplicar POO en modelado de entidades del mundo real.