Tema 11. Fundamentos de programación

Currículo: esta unidad cubre parte de los saberes básicos del Bloque E – Programación (TICO.1.E.1 y TICO.1.E.2) correspondiente a 1º Bachillerato. Además, se evalúan los criterios que puedes encontrar al final de esta página.

Tabla de contenidos

En la actualidad, la capacidad para entender la tecnología es una competencia fundamental  que otorga a quienes la dominan una ventaja competitiva muy importante. El estudio de la programación, tiene una utilidad práctica indiscutible, pero es que a nivel profesional es ya una de las habilidades más demandadas por una amplia variedad de sectores.

El estudio de este tema no te va a convertir en programador, pero sí que te va a dar la foto global de porqué son necesarios los programas, y también del proceso que se sigue para su construcción. 

Además, aprenderás los fundamentos de uno de los lenguajes de programación más demandados en la actualidad, y serás capaz de programar todo un universo de aplicaciones, incluso juegos.

Así que, te animo a que sigas con interés los contenidos que vienen, porque es seguro que te va a proporcionar o mejorar unas habilidades que son tremendamente valiosas en estos tiempos. 

11.1. Introducción a la lógica de programación

El estudio de los algoritmos es muy importante porque son la base del pensamiento computacional, una habilidad que es crítica en la actualidad

Este tipo de pensamiento nos permite descomponer problemas complejos en partes más manejables, lo que es fundamental para cualquier tarea de programación. Aprender sobre algoritmos, adoptando la lógica de programación, mejora nuestra capacidad de pensar de forma ordenada, lo cual es indispensable en la resolución de problemas tanto en la informática como en la vida cotidiana. 

Por lo tanto, estudiar cómo se construyen y optimizan los algoritmos va mucho más allá de programar, tiene que ver con la resolución de problemas en cualquier disciplina.

11.1.1. Algoritmos

Un algoritmo es, en esencia, un conjunto de instrucciones organizadas en un orden definido que describen un procedimiento paso a paso para realizar una tarea o resolver un problema.

Entonces, una receta de cocina ¿es un algoritmo?

Efectivamente.

En el contexto de la programación, estos pasos son instrucciones que el ordenador ejecuta para alcanzar un resultado.

Los algoritmos son fundamentales porque permiten a los programadores escribir códigos que no solo resuelven problemas específicos, sino que también son eficientes y están optimizados para consumir la menor cantidad posible de recursos (tiempo, memoria, procesador, etc.).

Por ejemplo, si necesitamos un algoritmo para buscar un libro en una biblioteca, el proceso podría ser algo así:

  • Inicio: entrar en la biblioteca.
  • Búsqueda: dirigirse a la sección correcta según el género del libro.
  • Selección: buscar el libro por su título en el orden alfabético.
  • Verificación: si el libro está, cogerlo; si no está, buscar otro libro o preguntar al bibliotecario.
  • Fin: salir de la biblioteca con el libro.

Cada uno de estos pasos constituye una parte del algoritmo y omitir cualquiera de ellos podría resultar en que no logremos nuestro objetivo -encontrar y llevarnos el libro-.

Además de la programación, usamos algoritmos en nuestra vida diaria, sin darnos cuenta: cuando organizamos nuestras tareas diarias, cuando decidimos la ruta más rápida para llegar a nuestro destino o incluso cuando hacemos la compra en el supermercado siguiendo un orden lógico que nos ahorre tiempo.

11.1.2. Formas de expresar un algoritmo

El ejemplo que vimos en el apartado anterior era relativamente sencillo, pero cuando nuestra solución está formada por cientos o miles de pasos, expresarlos en lenguaje natural es una tarea bastante tediosa, poco entendible por humanos y máquinas, y nada mantenible. Por eso, necesitamos estrategias más ágiles que nos permitan expresar los algoritmos.

Los algoritmos pueden expresarse de muchas maneras, pero nos centraremos en dos de las más comunes: los diagramas de flujo y el pseudocódigo.

Diagramas de flujo

Los diagramas de flujo son representaciones gráficas de los pasos que forman parte de un proceso, usando símbolos interconectados por flechas. Estos diagramas facilitan la visualización de la secuencia de operaciones y son muy útiles para planificar y explicar algoritmos complejos.

Estos son sus componentes principales:

TERMINADORRepresenta el inicio o el final del algoritmo
PROCESORepresenta cualquier tipo de acción
DECISIÓNPermite evaluar una condición y a partir del resultado encaminarnos por una alternativa u otra
ENTRADA/SALIDARepresenta la lectura de datos en la entrada y la impresión de datos en la salida
FLUJOIndica la siguiente orden que va a ejecutarse

Veamos cómo podríamos diseñar un diagrama de flujo que controlara mis acciones al intentar sacar un producto de una máquina de «vending»:

Como ves, hay ciertas reglas que debe cumplir todo diagrama de flujo. Entre las más comunes tenemos:

  • Debe iniciarse en un único punto.
  • Debe terminar, es decir, no puede haber bucles infinitos.
  • Las decisiones sólo tienen dos posibles salidas: si o no.

Para facilitar la creación de diagramas de flujo, existen muchas herramientas, pero yo te recomiendo estas:

  • Lucidchart: permite crear diagramas de flujo complejos de manera sencilla y colaborativa. Todo completamente online y basado en el navegador.
  • Draw.io: es una herramienta gratuita que se integra bien con Google Drive y ofrece amplias funcionalidades para diagramación.
  • Microsoft Visio: ideal para usuarios que buscan integración con otros productos de Microsoft Office.

Ejercicio 11.1 – Diagramas de flujo

Practica el diseño de diagramas de flujo expresando cada uno de estos algoritmos sencillos:

  1. Decidir qué ropa ponerse. Diseña un diagrama de flujo que ayude a decidir qué tipo de ropa ponerse en función de la temperatura. Considera tres rangos: menos de 15°C (ropa de invierno), entre 15°C y 25°C (ropa de entretiempo), y más de 25°C (ropa de verano).
  2. Elegir un medio de transporte. Crea un diagrama de flujo para elegir un medio de transporte para ir al trabajo. Si está lloviendo, elige el coche; si no, si la distancia es menor de 3 km, ir a pie; de lo contrario, usar bicicleta.
  3. Calcular el total a pagar en una tienda. Elabora un diagrama de flujo para calcular el total a pagar por un cliente en una tienda. El cliente ingresa la cantidad de productos y el precio por unidad. El total a pagar es simplemente la cantidad multiplicada por el precio por unidad.
  4. Verificar si un número es par o impar. Diseña un diagrama de flujo que determine si un número entero es par o impar.
  5. Freír un huevo. Crea un diagrama de flujo para el proceso de freír un huevo. Considera pasos como elegir una sartén, calentar aceite, romper el huevo, el tiempo de cocinado, etc.

Entrega: exporta cada uno de los diagramas en formato imagen y súbelos antes de la fecha límite indicada en classroom.

Pseudocódigo

Los diagramas de flujo son muy útiles porque nos permiten tomar decisiones de diseño y además nos permiten acercarnos un paso más del lenguaje natural al código de programación.

Sin embargo, todavía están lejos de este último.

El pseudocódigo es una forma de expresar un algoritmo usando frases y estructuras que simulan código de programación pero en un lenguaje más accesible y menos rígido. No está pensado para ser ejecutado por una máquina, sino para ser entendido por humanos.

Inicio
	Si está lloviendo entonces
    	Llevar paraguas
	Sino
    	No llevar paraguas
	Fin Si
Fin

Este método es especialmente útil para explicar lógicas complejas antes de codificarlas en un lenguaje de programación específico.

La utilidad de escribir nuestros algoritmos en pseudocódigo, es que no necesitamos conocer la sintaxis específica de un lenguaje de programación concreto, porque son tan expresivos que traducirlos a cualquier lenguaje de programación es muy rápido y sencillo.

De esta manera, especialistas de distintos lenguajes de programación, pueden discutir sobre el código de un programa escrito en un lenguaje común que entienden todos.

11.2. Fundamentos de la programación en Python

Nuestro objetivo a partir de aquí es hacer un repaso rápido de todas aquellas características de nuestro lenguaje de programación de referencia, que será Python, para poder empezar a programar pequeñas aplicaciones.

Empezaremos repasando su naturaleza, las características que lo definen, su estructura y su sintaxis. A lo largo de todo el proceso iremos poniendo pequeños ejemplos que ilustren su funcionamiento al mismo tiempo que iremos sentando las bases para construir un pequeño juego.

11.2.1. Lenguajes de programación

Un lenguaje de programación es un conjunto de reglas y símbolos que permiten a los programadores comunicarse con un ordenador

Pero, ¿para qué se necesitan si todos somos capaces de comunicarnos con un ordenador?

Claro, pero lo hacemos siempre a través de un programa, una aplicación, que nos permite interactuar con sus distintas partes: pantalla, sistema operativo, impresora, cámara, etc.

Por eso son necesarios los lenguajes de programación, porque son el idioma en el que se escriben los programas y aplicaciones.

Los lenguajes de programación se clasifican en varios tipos. Para que entiendas un poco mejor, por qué hay varios tipos, piensa en los idiomas.

Aunque podemos escribir, leer y usar cualquier idioma para cualquier cosa, algunos tienen unas ventajas que otros no. Por ejemplo, el comercio mundial está dominado por China, por lo que saber chino te proporciona una ventaja competitiva. Por su parte, la ciencia se escribe en inglés, así que, si eres científico y deseas publicar los resultados de tu investigación, es obligatorio hacerlo en inglés. O, por ejemplo, si te dedicas a la Teología, saber latín es fundamental y si te dedicas a la arqueología egipcia, conocer el idioma de los jeroglíficos es una necesidad.

A los lenguajes de programación les pasa lo mismo, podemos escribir prácticamente cualquier programa con una inmensa mayoría de lenguajes, pero unos están más indicados o han sido específicamente diseñados para resolver un tipo concreto de problemas o en un conjunto de contextos determinados.

Veamos los tipos que existen:

Lenguajes de bajo nivel

Un lenguaje de bajo nivel es un tipo de lenguaje de programación que está cerca del lenguaje máquina, permitiendo un control directo sobre el hardware, ejemplos de estos son el lenguaje ensamblador y el lenguaje máquina. 

  • Lenguaje máquina: es el nivel más básico de programación, compuesto de instrucciones binarias que la CPU puede ejecutar directamente.
  • Lenguaje ensamblador: es una representación simbólica del lenguaje máquina que utiliza mnemotécnicos en lugar de códigos binarios, facilitando la programación a nivel de hardware.

Lenguajes de alto nivel

Un lenguaje de alto nivel, por otro lado, está diseñado para ser más fácil de usar y entender por los humanos, alejándose de los detalles del hardware y proporcionando abstracciones más poderosas; ejemplos de lenguajes de alto nivel incluyen Python, Java y C++. Los dos subtipos principales que contiene son:

  • Imperativos: se centran en describir cómo se debe realizar una tarea mediante instrucciones secuenciales. Ejemplos: C, Pascal.
  • Declarativos: se enfocan en qué es lo que se quiere lograr sin especificar cómo se debe hacer. Ejemplos: SQL, HTML.

Lenguajes de script

Los lenguajes de script son lenguajes de programación que se utilizan principalmente para la automatización de tareas y el desarrollo de aplicaciones web, y son conocidos por su simplicidad y flexibilidad; ejemplos incluyen JavaScript y PHP.

Lenguajes de propósito específico

Los lenguajes de propósito específico están diseñados para resolver problemas específicos dentro de un dominio particular, como R para estadística y MATLAB para aplicaciones matemáticas y de ingeniería.

Introducción a Python

Python es un lenguaje de alto nivel, y de los más sencillos de aprender. Tiene una sintaxis muy clara y concisa que elimina cantidad de detalles que suelen ser difíciles de recordar y que agilizan mucho su aprendizaje.

Otra de sus ventajas es que cuenta con una enorme biblioteca estándar (las herramientas y utilidades que nos ofrece por defecto), que puede ser extendida con una de las ofertas de bibliotecas de programación más grandes del mundo, creadas y mantenidas por una extensa comunidad de programadores.

Además, es un lenguaje interpretado (no se compila antes de ejecutarse), lo que significa que ejecuta cada línea de código conforme la va leyendo, a diferencia de los lenguajes compilados, que deben leer todo el programa, traducirse a código máquina y luego ejecutarse.

Desarrollado por Guido van Rossum y lanzado por primera vez en 1991, Python ha ganado popularidad por su simplicidad y versatilidad, haciéndolo ideal tanto para principiantes como para desarrolladores experimentados.

Estas son las principales aplicaciones de Python:

  • Desarrollo web: usado en frameworks como Django y Flask.
  • Ciencia de datos: aporta potentísimas bibliotecas como pandas, NumPy y SciPy.
  • Inteligencia artificial: proporciona herramientas espectaculares como TensorFlow y scikit-learn.
  • Automatización: permite implementar tareas de automatización en sistemas operativos y aplicaciones.
  • Desarrollo de software: usado para la creación de aplicaciones de escritorio y móviles.

El estudio de Python en este tema te proporcionará una base sólida para explorar estas diversas aplicaciones, permitiéndote adquirir competencias que son altamente valoradas en el mercado laboral actual y en la investigación académica.

Python no solo es una herramienta para programar, sino una plataforma para innovar y resolver problemas en múltiples disciplinas.

11.2.2. Estructura de un programa

Antes de comenzar a ver código, necesitamos instalar un editor de código. Este tipo de programas no es más que un editor de texto, como Microsoft Word o Google Docs, pero específicamente diseñado para la escritura de código. Si además, a un editor le añadimos otras herramientas que agilizan la tarea de programar facilitando la vida a los programadores, lo que tenemos es un IDE –Integrated Development Environment o «Entorno de Desarrollo Integrado», que es lo que vamos a usar nosotros. Se llama PyCharm, y es uno de los entornos de programación más usado actualmente para el desarrollo de programas con Python a nivel profesional.

Para instalar PyCharm debemos proceder igual que siempre. Accedemos al Centro de Software de EducaAndOS y buscamos pycharm

Si nos lo marca como instalado, directamente cerramos la ventana. Si nos aparece el botón instalar, lo instalamos y cuando finalice, cerramos la ventana.

El programa aparecerá en Aplicaciones > Programación:

Lo abrimos y nos saldrá esta ventana:

Pulsamos sobre + Create New Project:

Le ponemos un nombre a nuestro proyecto, el que quieras, y tras asegurarte de que las opciones son iguales que las que aparecen en la imagen anterior, pulsas en Create.

Ya tenemos un proyecto para trabajar. Ahora lo que necesitamos es crear en el proyecto un archivo para escribir código.

Para ello, te sitúas sobre el nombre del proyecto, pulsas el botón derecho del ratón y seleccionas New > Python File:

Escribes el nombre que le quieres poner al archivo, yo le llamaré main:

Y pulsas en Python file.

Por último, para probar que todo ha ido bien, escribes esta instrucción:

Ahora comprobaremos que el código se está ejecutando correctamente. Lo comprobamos situándonos en cualquier parte vacía del archivo, clicamos con el botón derecho del ratón y pulsamos en Run.

Si el resultado es el siguiente, tienes un entorno de programación Python funcionando:

Ahora sí, podemos abordar el estudio de la estructura de un programa en Python.

La estructura de un programa en Python se caracteriza por su simplicidad, un aspecto que contribuye significativamente a la legibilidad y mantenibilidad del código. A continuación, veremos brevemente los componentes principales que forman parte de la estructura completa de un programa en Python.

Encabezado del script

Los programas en Python pueden comenzar con una línea especial llamada «shebang» (#!) seguida de la ruta al intérprete de Python. Esto es particularmente útil en sistemas Unix/Linux para ejecutar el script directamente desde la línea de comandos.

#!/usr/bin/env python3

Importaciones de módulos

Python incluye una cantidad enorme de funcionalidad, pero aun así, podemos extenderla para usar librerías (módulos) que nos proporcionan otras utilidades que podemos necesitar en momentos puntuales.

La importación de módulos permite, por tanto, reutilizar código existente de terceros. Las importaciones generalmente se colocan al inicio del script.

import math
import sys
from datetime import datetime

Estos tres módulos, nos ofrecen utilidades adicionales para realizar cálculos matemáticos, interactuar con el sistema operativo o trabajar con fechas/horas, respectivamente.

Definiciones de funciones y clases

La definición de funciones y clases es una parte clave de la organización del código en Python. Las funciones encapsulan bloques de código reutilizables, mientras que las clases permiten la programación orientada a objetos.

No es necesario que te quedes con la sintaxis, porque lo verás con más detalle más adelante, pero es bueno que empiece a sonarte.

def calcular_area_circulo(radio):
    return math.pi * radio ** 2

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

En el código anterior hemos definido una función para calcular el área de un círculo, y hemos creado una clase para modelar personas.

Comentarios

Los comentarios dentro del código son fundamentales para su comprensión y mantenimiento. Una cosa importante que es necesario entender es que, a pesar de que están en el código, no intervienen en el funcionamiento del mismo, ya que son líneas que no se ejecutan. Sólo están ahí para que los programadores se dejen mensajes sobre el funcionamiento del programa.

Python utiliza el símbolo # para los comentarios de una sola línea y las triple comillas (”’ o “””) para los comentarios multilínea.

# Este es un comentario de una sola línea

"""
Este es un comentario multilínea.
Puede ser utilizado para proporcionar descripciones detalladas
de funciones, clases o módulos.
También se suele usar para explicar porqué el programador
ha tomado una decisión de diseño concreta y no otra.
"""

Espaciado y sangría

Python utiliza la sangría para definir bloques de código, lo cual es extremadamente importante. Cada nivel de sangría (habitualmente cuatro espacios) indica un nuevo bloque. El espaciado adecuado es vital en Python, ya que define la estructura lógica del programa.

def saludar(nombre):
    if nombre:
        print(f"Hola, {nombre}!")
    else:
        print("¡Hola, Mundo!")

Veamos un ejemplo completo:

#!/usr/bin/env python3

import math
import sys
from datetime import datetime

def calcular_area_circulo(radio):
    """Calcula el área de un círculo dado su radio."""
    return math.pi * radio ** 2

class Persona:
    """Representa a una persona con un nombre y una edad."""
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

def main():
    """Función principal del programa."""
    radio = float(input("Introduce el radio del círculo: "))
    area = calcular_area_circulo(radio)
    print(f"El área del círculo es: {area}")

    persona = Persona("Juan", 30)
    print(f"Nombre: {persona.nombre}, Edad: {persona.edad}")

if __name__ == "__main__":
    main()

11.2.3. Tipos, constantes, variables, operadores y expresiones

En Python, como en cualquier lenguaje de programación, es importante entender cómo manejar los datos. Los tipos, constantes y variables son los componentes fundamentales que permiten almacenar y manipular estos datos de manera efectiva.

Tipos de datos

Los cuatro principales tipos de datos que se manejan con los enteros, los números de punto flotante, las cadenas de caracteres o string, y los booleanos:

  • Enteros (int): representan números enteros sin parte decimal. Ejemplo: x = 5
  • Números de punto flotante (float): representan números reales con parte decimal. Ejemplo: y = 3.14
  • Cadenas de texto (str): son secuencias de caracteres utilizadas para representar texto. Se pueden definir utilizando comillas simples o dobles. Ejemplo: mensaje = “Hola, mundo”
  • Booleanos (bool): los valores booleanos representan verdadero (True) o falso (False), y son útiles cuando debemos decidir entre dos posibles estados. Ejemplo: es_mayor = True.

Variables

Las variables son espacios en memoria que se utilizan para almacenar datos.

Piensa en las variables como en un cajón con un nombre. Normalmente usamos un cajón para camisetas, otro para bañadores y otro para complementos. El cajón puede estar vacío, o tener elementos dentro. Podemos meter cosas y sacarlas. También podemos dejarlo vacío. Las variables funcionan igual, el cajón sería un espacio en memoria donde podemos almacenar datos, cambiarlos o borrarlos.

Para acceder a esos datos usamos el nombre de la variable, que es un identificador que le ponemos a ese espacio de memoria..

En Python, no es necesario declarar el tipo de una variable explícitamente; se infiere del valor asignado.

# Ejemplos de variables
edad = 25
nombre = "Juan"
altura = 1.75
es_estudiante = True

Constantes

En todos los lenguajes de programación, las constantes son variables que no varían. Funcionan igual sintácticamente hablando, pero una vez que se les asigna un valor, no puede ser cambiado

En Python, no existe una manera estricta de definir constantes como en otros lenguajes de programación, pero por convención, se utilizan nombres de variables en mayúsculas para indicar que su valor no debe cambiar.

PI = 3.14159
GRAVEDAD = 9.81

Operadores

Los operadores son fundamentales en la programación, ya que permiten realizar cálculos, comparaciones y operaciones lógicas sobre los datos. A continuación, se presenta una descripción detallada de los diferentes tipos de operadores en Python y cómo se utilizan en las expresiones.

Comenzaremos con los operadores aritméticos clásicos, los que se utilizan para realizar operaciones matemáticas básicas:

  • Suma (+): suma dos operandos.
a = 10
b = 5
resultado = a + b  # resultado es 15

  • Resta (-): resta el segundo operando del primero.
resultado = a - b  # resultado es 5

  • Multiplicación (*): multiplica dos operandos.
resultado = a * b  # resultado es 50

  • División (/): divide el primer operando por el segundo. El resultado es un número de punto flotante.
resultado = a / b  # resultado es 2.0

  • División entera (//): divide el primer operando por el segundo y devuelve la parte entera del resultado.
resultado = a // b  # resultado es 2

  • Módulo (%): devuelve el resto de la división del primer operando por el segundo.
resultado = a % b  # resultado es 0

  • Exponenciación (**): eleva el primer operando a la potencia del segundo.
resultado = a ** b  # resultado es 100000

Sigamos con los operadores de comparación. Estos se utilizan para comparar dos valores y devuelven un valor booleano (True o False).

Su uso es similar a realizar una pregunta que se contesta con si o no.

Por ejemplo, ¿tienes más de 18 años? No. En Python se haría algo similar (edad > 18) = False.

Veamos los operadores que podemos encontrar en esta categoría:

  • Igual a (==): verifica si los operandos son iguales.
a=7
b=12
resultado = (a == b)  # resultado es False

  • Distinto de (!=): verifica si los operandos son diferentes.
resultado = (a != b)  # resultado es True

  • Mayor que (>) y mayor o igual que (>=): verifica si el primer operando es mayor que el segundo.
resultado = (a > b)  # resultado es False

  • Menor que (<) y Menor o igual que (<=): verifica si el primer operando es menor que el segundo.
resultado = (a < b ) # resultado es True

El tercer y último tipo de operadores que vamos a ver son los operadores lógicos. Estos nos permiten trabajar con valores de tipo booleano, y su resultado también lo será.

  • and: el operador and evalúa si el valor a la izquierda y el de la derecha son True, y en el caso de ser cierto, devuelve True. Si uno de los dos valores es False, el resultado será False. Es realmente un operador muy intuitivo que usamos en la vida real. Por ejemplo, si el semáforo está en verde y no vienen coches, cruzamos. Si ambas condiciones se cumplen, es decir que la variable semaforoVerde=True y la variable noVienenCoches=True, cruzaré, o visto de otra forma cruzar=(semaforoVerde and noVienenCoches).
  • or: el operador or devuelve True cuando al menos uno de los elementos es igual a True. Es decir, evalúa si el valor a la izquierda o el de la derecha son True.
  • not: simplemente invierte True por False y False por True.

Es importante notar que el orden de aplicación de los operadores puede influir en el resultado, por lo que es importante tener muy claro su prioridad de aplicación. De mayor a menor prioridad, el primero sería not, seguido de and y or.

Intenta averiguar el resultado de estos ejemplos sin ejecutar el programa:

print(False and False or True)
print(True or False and False)
print(0 and not 1 or 1 and not 0 or 1 and 0)

Expresiones compuestas

Las expresiones compuestas en Python combinan múltiples operadores y operandos para realizar cálculos más complejos. Es importante entender el orden de precedencia de los operadores para evaluar correctamente estas expresiones. Python sigue reglas de precedencia similares a las matemáticas tradicionales, donde las operaciones dentro de paréntesis se evalúan primero, seguidas por exponenciación, multiplicación/división/módulo, y finalmente suma/resta.

  • Paréntesis (): Evalúan las expresiones dentro de los paréntesis primero.
  • Exponenciación **.
  • Signos + y –: Signos unarios antes de una variable (por ejemplo, -a).
  • Multiplicación *, división /, división entera //, y módulo %.
  • Suma + y resta –.
  • Operadores de comparación: ==, !=, >, <, >=, <=.
  • Operadores lógicos not, and, or.

Veamos un ejemplo de expresiones compuestas:

# Variables iniciales
a = 5
b = 3
c = 2
d = 4

# Expresión compuesta
resultado = (a + b) * c / d  # Primero (a + b) = 8, luego 8 * c = 16, y finalmente 16 / d = 4.0

# Expresión más compleja
resultado = a + b * c ** d - (a / b)  # Precedencia: c ** d = 16, b * 16 = 48, a / b = 1.6667, a + 48 = 53, y finalmente 53 - 1.6667 = 51.3333

Expresiones con cadenas de texto

Las cadenas de texto también pueden ser manipuladas usando operadores. Python permite concatenar (unir) cadenas usando el operador +, y repetir cadenas usando el operador *. Por ejemplo:

# Concatenación de cadenas
nombre = "Juan"
saludo = "Hola, " + nombre + "!"  # saludo es "Hola, Juan!"

# Repetición de cadenas
repetir = "Hola" * 3  # repetir es "HolaHolaHola"

11.2.4. Interacción con el usuario

Cuando programamos, la interacción con el usuario es muy importante porque nos permite mostrarle datos al usuario (output), y también leer datos que el usuario introduce por el teclado (input). Python facilita enormemente este proceso, haciendo de las tareas de entrada/salida un trabajo realmente simle.

Mostrar datos en pantalla

Python utiliza la función print() para mostrar datos en la pantalla. Esta función es muy flexible y permite mostrar texto, variables y resultados de expresiones de manera fácil.

print(valor1, valor2, ..., sep=' ', end='\n')

Donde:

  • valor1, valor2, …: los valores que se desean mostrar. Pueden ser cadenas de texto, números, variables, etc.
  • sep: especifica el separador entre los valores (por defecto es un espacio).
  • end: especifica lo que se muestra al final de la salida (por defecto es un salto de línea).

Veamos un ejemplo práctico de su uso:

# Mostrar una cadena de texto
print("Hola, mundo")

# Mostrar múltiples valores
nombre = "Juan"
edad = 25
print("Nombre:", nombre, "Edad:", edad)

# Cambiar el separador y el final de línea
print("Python", "es", "genial", sep='-', end='!\n')

A veces, podemos necesitar usar la sintaxis F-strings, que nos facilita la escritura de salidas en pantalla:

nombre = "Ana"
edad = 30
print(f"Nombre: {nombre}, Edad: {edad}")

Obtener datos de teclado

La función input() se utiliza para leer datos introducidos por el usuario desde el teclado. Esta función siempre devuelve una cadena de texto, por lo que es necesario convertir los datos al tipo adecuado si se espera un valor numérico.

# Leer una cadena de texto
nombre = input("Introduce tu nombre: ")
print("Hola", nombre)

# Leer un número entero
edad = int(input("Introduce tu edad: "))
print("Tienes ", edad, " años")

# Leer un número de punto flotante
altura = float(input("Introduce tu altura en metros: "))
print("Mides", altura, " metros")

11.2.5. Estructuras de control

Las estructuras de control nos permiten dirigir el flujo de ejecución del programa según ciertas condiciones. Incluyen las estructuras condicionales, repetitivas y de salto. Estas estructuras proporcionan la capacidad de tomar decisiones, repetir bloques de código y manejar situaciones excepcionales de manera organizada y eficiente.

Estructuras condicionales

Las estructuras condicionales permiten ejecutar bloques de código solo si se cumplen ciertas condiciones. Python utiliza las palabras clave if, elif (abreviatura de «else if») y else para definir estas condiciones.

edad = 20

if edad < 18:
    print("Eres menor de edad")
elif edad >= 18 and edad < 65:
  	print("Eres un adulto")
else:
    print("¡Jubilado! Enhorabuena")

Estructuras repetitivas

Las estructuras repetitivas nos permiten repetir un bloque de código las veces que necesitemos. Popularmente se les conoce como bucles, y en Python tenemos dos: los bucles for y los bucles while.

El bucle for se utiliza para repetir un bloque de código cuando sabemos exactamente cuantas veces queremos repetirlo.

for numero in range(5):
  print(numero)  # Muestra 0 1 2 3 4

for numero in range(5,7):
  print(numero) # Muestra 5 6
    
for numero in range(5,11,2):
  print(numero) # Muestra 5 7 9
    
for numero in range(9,2,-2):
  print(numero) # Muestra 9 7 5 3

Como puedes ver por el fragmento de código anterior, range usa 1, 2 o 3 parámetros. Cuando usa uno, el bloque se repetirá el número de veces que se indique -1 (sin incluir al número). Cuando se usan dos parámetros, el primero indica el punto inicial y el segundo el punto final (sin incluir este último). Cuando se usan tres parámetros, los dos primeros funcionan igual y el tercero indica el salto de avance desde el primero al siguiente hasta llegar al último.

EL bucle while, a diferencia del for, se repite siempre que una condición especificada sea verdadera.

contador = 0

while contador < 5:
    print(contador)
    contador = contador + 1

Estructuras de salto

Permiten alterar el flujo normal de ejecución de las estructuras de control.

break, se utiliza para terminar el bucle actual de manera anticipada.

for numero in range(10):
    if numero == 5:
        break
    print(numero) # Muestra 0 1 2 3 4

continue, se usa para omitir el resto del bloque de código en la iteración actual y pasar a la siguiente iteración del bucle.

for numero in range(10):
    if numero == 5:
        continue
    print(numero) # Muestra 0 1 2 3 4 6 7 8 9

Ahora, ya tienes una base suficiente como para empezar a resolver algunos problemas sencillos. A continuación, encontrarás los enunciados de 20 problemas con sus respectivas soluciones. Si quieres aprender, te recomiendo que intentes resolver cada problema una y otra vez por ti mismo, y sólo acudas a la solución cuando llegues a un callejón sin salida. Aprender a programar no es rápido ni sencillo, sólo se logra con paciencia y tesón.

Ejercicios resueltos de estructuras de control

1. Escribe un programa que pida al usuario su edad y determine si es mayor de edad o no.
2. Escribe un programa que pida un número al usuario y determine si es par o impar.
3. Escribe un programa que pida dos números al usuario y muestre cuál es mayor.
4. Escribe un programa que pida un número al usuario y determine si es positivo, negativo o cero.
5. Escribe un programa que pida un número del 1 al 7 y muestre el día de la semana correspondiente.
6. Escribe un programa que pida una temperatura en grados Celsius y la convierta a Fahrenheit.
7. Escribe un programa que pida una palabra y la muestre al revés.
8. Escribe un programa que pida un número y muestre su tabla de multiplicar del 1 al 10.
9. Escribe un programa que pida un número y calcule la suma de todos los números desde 1 hasta ese número.
10. Escribe un programa que pida un número y calcule su factorial.
11. Escribe un programa que pida una palabra y determine si es un palíndromo (se lee igual de izquierda a derecha que de derecha a izquierda).
12. Escribe un programa que pida un número y muestre si es un número primo o no.
13. Escribe un programa que pida un número y muestre los números impares desde 1 hasta ese número.
14. Escribe un programa que pida una frase y cuente cuántas vocales tiene.
15. Escribe un programa que pida un número y muestre todos los números pares desde 1 hasta ese número.
16. Escribe un programa que pida una cantidad de segundos y la convierta a horas, minutos y segundos.
17. Escribe un programa que pida una nota (0-10) y muestre si está suspenso (menos de 5), aprobado (5-6), bien (7-8), notable (9) o sobresaliente (10).
18. Escribe un programa que pida al usuario un número y muestre si es un número Armstrong (un número igual a la suma de sus propios dígitos cada uno elevado a la potencia de la cantidad de dígitos).
19. Escribe un programa que pida dos números y muestre su máximo común divisor (MCD).
20. Escribe un programa que pida un número y muestre la secuencia de Fibonacci hasta ese número.

11.2.6. Modularización

La modularización es una técnica fundamental en la programación que permite dividir un programa en partes más pequeñas, manejables y reutilizables, conocidas como módulos o funciones. Esta práctica mejora la legibilidad y mantenibilidad del código, y facilita la colaboración entre múltiples desarrolladores.

Cada módulo tiene una funcionalidad definida y puede ser desarrollado y probado de manera independiente.

Desde el punto de vista de la escritura de código, las funciones son bloques de código que realizan una tarea específica y se pueden invocar -ser llamadas- desde otras partes del programa. En Python se definen utilizando la palabra clave def seguida del nombre de la función y paréntesis que pueden incluir parámetros.

# Esquema conceptual de la definición de una función
def nombre_de_la_funcion(parametro1, parametro2):
    # Bloque de código
    return valor_de_retorno

Por ejemplo, esta función saluda al usuario que hayamos indicado en el parámetro nombre:

def saludar(nombre):
    print(f"Hola, {nombre}")

saludar("Ana")  # Output: Hola, Ana

Como hemos indicado más arriba, las funciones pueden aceptar parámetros, que son variables que se pasan a la función para que pueda utilizarlas en su bloque de código. Además, las funciones pueden devolver un valor utilizando la palabra clave return.

def sumar(a, b):
    return a + b

resultado = sumar(5, 3)
print(resultado)  # Salida: 8

Veamos cuál sería el flujo de ejecución del programa anterior:

  • El ordenador lee las líneas 1 y 2, pero no las ejecuta (ya que la definición de una función sólo se ejecuta cuando la función es llamada).
  • Se ejecuta la línea 4, de derecha a izquierda, por tanto, lo primero que se hace es llamar a sumar(5,3).
  • Se busca la definición de la función sumar, se encuentra en la línea 1, y se sustituyen los parámetros por los valores, es decir, a=5 y b=3.
  • Con los parámetros establecidos se entra a ejecutar el bloque interior de la función: return 5+3.
  • La función devuelve 8 y el programa vuelve al punto en el que se llamó a la función, línea 4, y como consecuencia de ello se hace resultado=8.
  • Se ejecuta la línea 5, mostrándose 8 en pantalla.

Además de lo anterior, cuando se trabajan con funciones es muy importante entender el alcance de las variables.

El alcance de una variable («scope») determina dónde puede ser utilizada dentro del código.

Las variables definidas dentro de una función tienen un alcance LOCAL, es decir, solo pueden ser utilizadas dentro de esa función. Las variables definidas fuera de cualquier función tienen un alcance GLOBAL y pueden ser utilizadas en cualquier parte del programa.

Por ejemplo, en el siguiente programa, la variable mensaje se ha creado en el interior de la función (línea 2), por tanto, cuando la usamos en la línea 6 (fuera de la función), nos va a generar un error.

def mostrar_mensaje():
    mensaje = "Hola desde la función"
    print(mensaje)

mostrar_mensaje()
print(mensaje)  # Esto generará un error porque 'mensaje' es una variable local

Cuando nuestros programas empiezan a crecer, acumulando cientos o miles de líneas de código, por mucho que tengamos nuestro código organizado en funciones, seguirá siendo algo muy difícil de mantener. Por eso, podemos ir un paso más allá en la organización del código, usando módulos.

Los módulos son archivos que contienen definiciones de funciones, de esta manera, podemos aliviar la cantidad de código que tenemos en nuestro programa principal, y cuando necesitemos usar una función, simplemente importamos el archivo que contiene su definición.

Por ejemplo, vamos a crear un archivo llamado matematicas.py donde incluiremos la definición de algunas funciones:

def sumar(a, b):
    return a + b

def restar(a, b):
    return a - b

Si luego, en nuestro programa principal necesitamos usar las funciones sumar o restar, o cualquier otra incluida en ese módulo, lo importamos y lo usamos.

import matematicas

resultado_suma = matematicas.sumar(10, 5)
resultado_resta = matematicas.restar(10, 5)

print(f"Suma: {resultado_suma}")
print(f"Resta: {resultado_resta}")

Además, esa instrucción import no sólo nos permite importar un módulo que hayamos creado nosotros, sino cualquier módulo sea quien sea el propietario. Y aquí es donde radica una de los mayores atractivos de Python: dispone de un catálogo de módulos extremadamente potentes que podemos usar para programar cualquier cosa.

Por ejemplo, usando el módulo fpdf podemos crear un PDF con muy pocas líneas de código:

Para poder usar un módulo de terceros, debes instalarlo previamente ejecutando en la consola:
pip install fpdf

from fpdf import FPDF

pdf = FPDF(orientation='P', unit='mm', format='A4')
pdf.add_page()
pdf.set_font('Arial','',16)
pdf.text(x=60,y=50,txt='Mi primer PDF')
pdf.output('unpdf.pdf','F')

Si ahora vamos al directorio donde se encuentra nuestro archivo de código, veremos cómo se ha creado un archivo nuevo llamado unpdf.pdf con este contenido:

Así de sencillo es crear un PDF usando un programa escrito por nosotros mismos. Esto tiene innumerables utilidades para automatizar procesos, como por ejemplo: generar diplomas, boletines de notas, informes, imprimir estadísticas, etc…

Otro ejemplo muy interesante podría ser el de visualizar gráficamente datos que tengamos recogidos por sensores. Un módulo muy popular que nos permite hacer esto es matplotlib. Vamos a usarlo para graficar las temperaturas de la última semana en Madrid y Barcelona:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
dias = ['L', 'M', 'X', 'J', 'V', 'S', 'D']
temperaturas = {'Madrid':[28.5, 30.5, 31, 30, 28, 27.5, 30.5], 'Barcelona':[24.5, 25.5, 26.5, 25, 26.5, 24.5, 25]}
ax.plot(dias, temperaturas['Madrid'], color = 'tab:purple')
ax.plot(dias, temperaturas['Barcelona'], color = 'tab:green')
plt.show()

El resultado tras ejecutar el programa anterior, sería:

Como ves, podemos hacer cualquier cosa que se nos ocurra si dominamos la sintaxis de Python para importar módulos y conocemos las instrucciones que nos permiten programar los módulos que importamos (esto último debes consultarlo en la web de cada módulo). Puedes revisar este sencillo manual de matplotlib para que compruebes de primera mano lo sencillo que es.

11.2.7. Estructuras de datos

Las estructuras de datos son una parte fundamental de la programación, ya que permiten organizar y gestionar de manera eficiente los datos en la memoria. En Python, existen varias estructuras de datos integradas que son ampliamente utilizadas debido a su flexibilidad. Aunque las principales estructuras de datos que se suelen manejar incluyen listas, tuplas, conjuntos, diccionarios y clases, nosotros por los conocimientos que tenemos de programación y los usos que vamos a darle, sólo aprenderemos lo básico de listas y diccionarios.

Listas

Las listas son colecciones ordenadas y mutables de elementos. Esto significa que se pueden modificar (agregar, eliminar o cambiar elementos) después de haber sido creadas. Las listas en Python se definen utilizando corchetes [] y los elementos se separan por comas.

# Crear una lista
frutas = ["manzana", "platano", "cereza"]

# Acceder a elementos de la lista
print(frutas[0])  # Salida: manzana
print(frutas[1])  # Salida: banana

# Modificar un elemento de la lista
frutas[1] = "kiwi"
print(frutas)  # Salida: ['manzana', 'kiwi', 'cereza']

También disponemos de muchas funciones integradas en el lenguaje, que nos permiten realizar operaciones comunes con las listas.

# Agregar elementos
frutas.append("naranja")
print(frutas)  # Salida: ['manzana', 'kiwi', 'cereza', 'naranja']

# Eliminar elementos
frutas.remove("kiwi")
print(frutas)  # Salida: ['manzana', 'cereza', 'naranja']

# Insertar elementos en una posición específica
frutas.insert(1, "pera")
print(frutas)  # Salida: ['manzana', 'pera', 'cereza', 'naranja']

# Obtener la longitud de la lista
longitud = len(frutas)
print(longitud)  # Salida: 4

Por último, necesitamos saber cómo podemos recorrer una lista para poder realizar comprobaciones u operaciones sobre cada uno de los elementos que contiene.

# Definir una lista
frutas = ["manzana", "pera", "cereza"]

# Recorrer la lista con un bucle for
for fruta in frutas:
    print(fruta)

En este ejemplo, el bucle for itera sobre cada elemento de la lista frutas, asignando cada elemento a la variable fruta en cada iteración, y luego imprime el valor de fruta.

Esto mismo también puede hacerse recorriendo la lista por medio de un índice que indica la posición que ocupa cada elemento en la lista:

# Definir una lista
frutas = ["manzana", "pera", "cereza"]

# Recorrer la lista con un bucle for
for indice in range(0,len(frutas)):
    print(frutas[indice])

¿Cuándo debes usar un método u otro? Te lo dirá las necesidades que tengas en cada momento para resolver un problema concreto.

Diccionarios

Los diccionarios son colecciones desordenadas de pares clave-valor. Cada clave debe ser única, y se utiliza para acceder al valor asociado. Los diccionarios se definen utilizando llaves {} y pares clave-valor separados por dos puntos :.

Por ejemplo vamos a crear un diccionario persona que almacene los datos personales:

# Crear un diccionario
persona = {
    "nombre": "Juan",
    "edad": 30,
    "ciudad": "Madrid"
}

# Acceder a valores por clave
print(persona["nombre"])  # Salida: Juan
print(persona["edad"])  # Salida: 30

# Modificar un valor
persona["edad"] = 31
print(persona)  # Salida: {'nombre': 'Juan', 'edad': 31, 'ciudad': 'Madrid'}

# Agregar un nuevo par clave-valor
persona["profesion"] = "Ingeniero"
print(persona)  # Salida: {'nombre': 'Juan', 'edad': 31, 'ciudad': 'Madrid', 'profesion': 'Ingeniero'}

# Eliminar un par clave-valor
del persona["ciudad"]
print(persona)  # Salida: {'nombre': 'Juan', 'edad': 31, 'profesion': 'Ingeniero'}

De la misma manera que hicimos para las listas, también podemos recorrer los diccionarios. Recorrer un diccionario implica iterar sobre sus pares clave-valor. En Python, esto se puede hacer utilizando el método items(), que devuelve una vista de pares clave-valor del diccionario.

# Definir un diccionario
persona = {
    "nombre": "Juan",
    "edad": 30,
    "ciudad": "Madrid"
}

# Recorrer el diccionario con un bucle for
for clave, valor in persona.items():
    print(f"{clave}: {valor}")

En este ejemplo, el método items() se utiliza para obtener una vista de pares clave-valor del diccionario persona. El bucle for itera sobre cada par, asignando la clave a clave y el valor a valor, y luego imprime ambos.

Pero puede que necesitemos recorrer sólo claves o sólo valores. Para esos casos también disponemos de métodos que agilizan estos procesos:

# Recorrer solo las claves del diccionario
for clave in persona.keys():
    print(clave)

# Recorrer solo los valores del diccionario
for valor in persona.values():
    print(valor)

En el primer ejemplo, el método keys() se utiliza para obtener una vista de las claves del diccionario persona. En el segundo ejemplo, el método values() se utiliza para obtener una vista de los valores del diccionario persona.

Ejercicios resueltos de estructuras de datos

1. Escribe un programa que calcule la suma de todos los elementos de esta lista [4, 12, 15, 9, 31].
2. Escribe un programa que encuentre el mayor número de esta lista [4, 12, 65, 9, 31].
3. Escribe un programa que calcule cuántos elementos hay en esta lista [4, 12, 15, 9, 31].
4. Escribe un programa que muestre solo los número impares de esta lista [4, 12, 15, 9, 31].
5. Escribe un programa que muestre esta lista invertida [4, 12, 15, 9, 31].
6. Escribe un programa que cree un diccionario con el nombre, la edad y la ciudad de una persona, obteniendo estos datos del usuario por teclado, y luego muestre el diccionario..
7. Amplía el ejercicio anterior para que se le pida al usuario una nueva edad, modifique la edad que tenía la persona y muestre nuevamente el diccionario actualizado.
8. Amplía el ejercicio anterior para que añada al diccionario de la persona su dirección de correo electrónico, y muestre el diccionario actualizado.
9. Amplía el ejercicio anterior para que se le pida al usuario una clave y elimine ese par clave-valor del diccionario persona. Muestra el diccionario actualizado.
10. Amplía el ejercicio anterior para mostrar en pantalla sólo los valores del diccionario.

11.3. Depuración

Una vez que hemos diseñado el código de nuestra aplicación, es posible que observemos algún comportamiento erróneo o alguna inconsistencia. 

En esta parte del desarrollo de la aplicación, es fundamental encontrar y corregir errores –bugs– en el código. De ello se encarga la depuración o «debugging». Un proceso efectivo de depuración asegura que el software sea confiable, eficiente y libre de fallos que puedan afectar su funcionamiento.

La depuración implica examinar el código, identificar dónde y por qué ocurren los errores, y corregirlos. Es como ser un detective en el mundo de la programación: se buscan pistas (errores), se analizan las causas (el porqué de los errores) y se resuelven los problemas (se corrigen los errores).

(1) En el mejor de los casos, sabremos que nuestro código presenta errores porque el propio entorno de desarrollo -IDE, como PyCharm- nos lo va a marcar con llamativos mensajes en rojo, son los errores de sintaxis.

(2) En otras ocasiones, sabremos que nuestro programa contiene errores, porque a pesar de que el entorno de desarrollo no nos muestra errores de sintaxis, lo que obtenemos no tiene sentido o no son datos coherentes. Inicialmente no sabemos donde está el error, pero sabemos que algo no está funcionando correctamente.

(3) Pero, sin duda, los errores más temibles para todos los programadores, son los llamados errores intermitentes. Son aquellos que no se producen en cada ejecución del programa, sino sólo bajo ciertas condiciones especiales. Encontrar estos últimos es una tarea tediosa que consume mucho tiempo y esfuerzo, por eso es fundamental ir realizando pruebas a nuestro código para intentar minimizarlos.

Como hemos avanzado, casi todos los IDE incorporan ya funciones para la depuración. El módulo de nuestro entorno de desarrollo encargado de esta tarea se llama «debugger».

En PyCharm, podemos acceder a las herramientas de depuración con el icono del «bicho» -bug- (situado en la parte superior derecha del programa):

Cuando pulsamos en la ejecución del programa en modo depuración, se activan comprobaciones adicionales que nos permiten comprobar si todo va bien. Pero, ciertos errores o inconsistencias no serán detectados, por lo que deberemos hacer una ejecución manual paso a paso.

Una buena manera de hacerlo es situar un «breakpoint» o punto de ruptura. Se trata de marcar una línea de código donde queremos que se pare la ejecución del programa. Esto lo hacemos pulsando con el ratón junto al número de línea que queremos marcar (aparecerá un punto rojo). Observa la línea de código número 2 de la imagen.

Una vez marcadas las líneas donde queremos que el programa pare, lo ejecutamos en modo depuración. El programa comenzará a ejecutarse y se parará en cada breakpoint. Para avanzar podemos utilizar una variedad de iconos disponibles. El primero de ellos -señalado con flecha rosa- nos permite avanzar línea a línea. Es decir, cada vez que lo pulsemos el programa ejecutará la siguiente instrucción prevista en nuestro código.

Las flechas moradas indican los botones que podemos pulsar si queremos parar la ejecución o terminarla hasta el final. Si queremos que termine, debemos retirar los breakpoints.

Pero, la zona más importante de todas, es la que aparece rodeada de amarillo, el inspector de variables. En esta zona, veremos cómo aparecen los nombres de las variables y otras estructuras de datos «visibles» en ese momento de la ejecución, y los valores que tienen en ese punto. Así, conforme vamos ejecutando manualmente nuestro programa paso a paso, podemos ir comprobando si los valores que van recogiendo las variables son los correctos o no.

Estas herramientas de depuración -y la ejecución paso a paso de programas-, no son solo útiles para detectar errores o corregir inconsistencias, sino que son una excelente manera de entender la ejecución de los programas. 

Cuando llega a nuestras manos un algoritmo, a primera vista complejo, podemos desentrañar todos sus misterios haciéndole una ejecución paso a paso con el depurador para ver cómo funciona.

Como siempre, debemos recordar, que el proceso de desarrollo de software es una tarea realmente compleja. Cuando tenemos un programa con miles de líneas de código distribuidas en cientos de archivos interrelacionados, encontrar un error, aunque sea utilizando un depurador es un trabajo realmente complejo que suele consumir una cantidad ingente de recursos tanto en tiempo como en costes económicos.

Por eso, siempre es una regla de oro, seguir las recomendaciones, las buenas prácticas, los patrones de diseño y todos aquellos protocolos probados que nos previenen de la mayor parte de los errores que dan al traste con el éxito de nuestros proyectos. 

11.4. Cómo abordar problemas complejos

Resolver problemas complejos es una habilidad fundamental en la programación y en cualquier disciplina que requiera pensamiento crítico. Vamos a ver algunas estrategias que podemos poner en práctica para facilitar la construcción de una solución.

11.4.1. Divide y vencerás

El enfoque «divide y vencerás» es una técnica ampliamente utilizada para abordar problemas complejos. Consiste en descomponer un problema grande en problemas más pequeños y manejables, resolver cada uno de estos subproblemas individualmente y luego combinar sus soluciones para resolver el problema original.

Por ejemplo, supongamos que necesitas desarrollar un sistema de gestión de biblioteca. Este problema puede parecer enorme, pero se puede descomponer en subproblemas como: gestión de libros (agregar, eliminar, actualizar información), gestión de usuarios (registrar, eliminar, actualizar información), préstamos y devoluciones de libros. Cada uno de estos subproblemas puede abordarse individualmente, y una vez resueltos, se pueden integrar para crear el sistema completo.

Además, otra ventaja de esta estrategia es que podemos trabajar en paralelo en varios subproblemas a la vez para minimizar el tiempo de desarrollo.

11.4.2. Estructuras de datos adecuadas

Seleccionar los algoritmos y estructuras de datos adecuados es clave para resolver problemas de manera eficiente. Los algoritmos son pasos secuenciales para realizar una tarea, y las estructuras de datos son maneras de organizar y almacenar datos.

Por ejemplo, para un sistema que necesita buscar y ordenar una gran cantidad de datos, podrías utilizar una lista para almacenar los datos y aplicar un algoritmo de búsqueda binaria para búsquedas rápidas y el algoritmo de ordenación rápida (quicksort) para ordenar los datos eficientemente.

11.4.3. Prototipado

El prototipado puede llegar a ser una etapas muy importante en el desarrollo de soluciones a problemas complejos. Crear prototipos permite visualizar y evaluar rápidamente las soluciones propuestas, para posteriormente hacerle pruebas que aseguren que las soluciones funcionen correctamente.

Por ejemplo, si estás desarrollando una aplicación web, primero podrías crear un prototipo de la interfaz de usuario con funcionalidades básicas. Luego, podrías escribir pruebas unitarias para cada funcionalidad (por ejemplo, añadir un usuario, eliminar un libro) y pruebas de integración para asegurarte de que todas las partes de la aplicación funcionen bien juntas.

11.4.4. Documentación

Una buena documentación facilita la comprensión del código y su mantenimiento a largo plazo, además permite que sea posible la colaboración efectiva entre los miembros del equipo.

Por ejemplo, en un proyecto de desarrollo de software, podrías utilizar un repositorio de Git para gestionar el código. Cada desarrollador puede trabajar en su propia rama, y las revisiones de código se pueden realizar mediante «pull requests». La documentación puede incluir un archivo «README» detallado, comentarios en el código y documentos separados para aspectos complejos del sistema.


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *