Repaso while

# =============================================================================
# BUCLES WHILE EN PYTHON
# =============================================================================
# Un bucle "while" repite un bloque de código MIENTRAS se cumpla una condición.
# Es ideal cuando no sabemos de antemano cuántas veces necesitamos repetir algo.
#
# Estructura básica:
#
#   while condición:
#       instrucción 1   ← estas líneas se repiten mientras la condición sea True
#       instrucción 2
#
# ¡CUIDADO! Si la condición nunca se vuelve False, el bucle no termina nunca
# (bucle infinito). Siempre hay que asegurarse de que algo dentro del bucle
# hace que la condición cambie.
#
# En este archivo veremos 6 ejemplos prácticos:
#   1. Calcular el factorial de un número
#   2. Repetir algo hasta que el usuario decida parar
#   3. Tabla de multiplicar del 7
#   4. Sumar los números del 0 al 100
#   5. Saludar a varios usuarios hasta que no introduzcan nombre
#   6. Acumular números introducidos por el usuario
# =============================================================================


# =============================================================================
# EJEMPLO 1: CÁLCULO DEL FACTORIAL CON UN BUCLE WHILE
# =============================================================================
# El factorial de un número n (escrito n!) es la multiplicación de todos los
# números enteros desde 1 hasta n.
# Ejemplo: 5! = 1 × 2 × 3 × 4 × 5 = 120
#
# Interacción esperada:
#   Introduce un numero: 5
#   El factorial de 5 es 120
# =============================================================================

numero = int(input("Introduce un numero: "))
# input() siempre devuelve texto (string). int() lo convierte a número entero.
# Si el usuario escribe "5", sin int() tendríamos la cadena "5", no el número 5.
# PRUEBA: quita el int() y observa el error que aparece al hacer cálculos.

factorial = 1
# Inicializamos factorial a 1, no a 0.
# Si lo inicializáramos a 0, cualquier multiplicación daría 0 (0 × lo que sea = 0).
# Esta variable irá acumulando el resultado de las multiplicaciones.

contador = 1
# El contador empieza en 1 porque la multiplicación parte de 1.
# Esta variable controla el bucle: irá de 1 hasta "numero".

while contador <= numero:
    # La condición comprueba si contador todavía no ha superado "numero".
    # Cuando contador > numero, el bucle se detiene.
    # Ejemplo con numero=4: el bucle se ejecuta para contador = 1, 2, 3, 4

    factorial = factorial * contador
    # Multiplicamos el factorial acumulado por el contador actual.
    # Es lo mismo que: factorial *= contador  (forma abreviada)
    # Paso a paso con numero=4:
    #   Vuelta 1: factorial = 1 × 1 = 1
    #   Vuelta 2: factorial = 1 × 2 = 2
    #   Vuelta 3: factorial = 2 × 3 = 6
    #   Vuelta 4: factorial = 6 × 4 = 24  → El factorial de 4 es 24 ✓

    contador = contador + 1
    # Incrementamos el contador para avanzar al siguiente número.
    # Es lo mismo que: contador += 1  (forma abreviada)
    # SIN esta línea, contador siempre valdría 1 y el bucle nunca terminaría.

print(f"El factorial de {numero} es {factorial}")
# Las f-strings permiten insertar variables dentro del texto con {}.
# ALTERNATIVA sin f-string: print("El factorial de", numero, "es", factorial)
# ALTERNATIVA avanzada: Python tiene math.factorial(n) que hace esto automáticamente:
#   import math
#   print(math.factorial(5))  → 120


# =============================================================================
# EJEMPLO 2: BUCLE CONTROLADO POR EL USUARIO (SEGUIR / PARAR)
# =============================================================================
# Este ejemplo muestra cómo dejar que el USUARIO decida cuándo parar el bucle.
# Contamos cuántas veces decide continuar.
#
# Interacción esperada:
#   0
#   ¿Deseas seguir? (Sí/No): Sí
#   1
#   ¿Deseas seguir? (Sí/No): Sí
#   2
#   ¿Deseas seguir? (Sí/No): No
# =============================================================================

seguir = "Sí"
# Inicializamos la variable centinela con "Sí" para que el bucle empiece.
# Una variable "centinela" es aquella cuyo valor controla si el bucle continúa.
# IMPORTANTE: debe coincidir exactamente con la condición del while.

contador = 0
# Empezamos el contador en 0 y lo iremos mostrando en cada vuelta.

while seguir == "Sí":
    # El bucle continúa MIENTRAS el usuario escriba exactamente "Sí".
    # Si escribe "si", "SI", "sí" con minúscula... el bucle se detiene.
    # ALTERNATIVA más flexible: while seguir.lower() == "sí":
    #   Con .lower() convertimos a minúsculas y aceptamos "Sí", "SÍ", "sí"...

    print(contador)
    # Mostramos el valor actual del contador antes de preguntar.

    seguir = input("¿Desas seguir? (Sí/No): ")
    # Aquí el usuario puede escribir "Sí" o "No".
    # Este input SOBREESCRIBE el valor anterior de "seguir".
    # Si escribe "No" (o cualquier cosa que no sea "Sí"), el bucle termina.

    contador = contador + 1
    # Incrementamos el contador en cada vuelta.


# =============================================================================
# EJEMPLO 3: TABLA DE MULTIPLICAR DEL 7
# =============================================================================
# Recorremos los números del 1 al 10 y multiplicamos cada uno por 7.
#
# Resultado esperado:
#   1 x 7 = 7
#   2 x 7 = 14
#   3 x 7 = 21
#   ...
#   10 x 7 = 70
# =============================================================================

numero = 1
# Reutilizamos el nombre "numero" (la variable del ejemplo anterior ya no se usa).
# El número empieza en 1 porque las tablas de multiplicar van del 1 al 10.

while numero <= 10:
    # El bucle se ejecuta mientras numero sea menor o igual a 10.
    # Se ejecutará exactamente 10 veces: para 1, 2, 3, ..., 10.

    print(f"{numero} x 7 = {numero * 7}")
    # Mostramos la operación completa y su resultado.
    # numero * 7 se calcula directamente dentro de la f-string.
    # ALTERNATIVA: resultado = numero * 7 y luego print(f"{numero} x 7 = {resultado}")

    numero = numero + 1
    # Avanzamos al siguiente número.
    # Sin esta línea: número siempre sería 1 → bucle infinito imprimiendo "1 x 7 = 7"

# ALTERNATIVA con for (más natural para recorrer rangos conocidos):
#   for numero in range(1, 11):       # range(1,11) genera: 1, 2, 3, ..., 10
#       print(f"{numero} x 7 = {numero * 7}")
#
# RETO: modifica el código para que pregunte al usuario qué tabla quiere ver.


# =============================================================================
# EJEMPLO 4: SUMAR TODOS LOS NÚMEROS DEL 0 AL 100
# =============================================================================
# Acumulamos la suma de 0 + 1 + 2 + 3 + ... + 100 = 5050
#
# Resultado esperado:
#   5050
# =============================================================================

contador = 0
# El contador empieza en 0 porque queremos sumar desde 0.

suma = 0
# La variable acumuladora también empieza en 0.
# Irá almacenando la suma parcial en cada vuelta.
# NUNCA inicialices una suma acumuladora a otro valor que no sea 0,
# ya que añadiría un "extra" a todos los cálculos.

while contador <= 100:
    # El bucle recorre todos los números de 0 a 100, ambos incluidos.

    suma = suma + contador
    # Añadimos el valor actual del contador a la suma acumulada.
    # Es lo mismo que: suma += contador
    # Paso a paso:
    #   Vuelta 0: suma = 0 + 0 = 0
    #   Vuelta 1: suma = 0 + 1 = 1
    #   Vuelta 2: suma = 1 + 2 = 3
    #   Vuelta 3: suma = 3 + 3 = 6
    #   ... y así hasta 100

    contador = contador + 1
    # Avanzamos al siguiente número.

print(suma)
# Imprime 5050. Existe una fórmula matemática directa: n*(n+1)/2 → 100*101/2 = 5050
# ALTERNATIVA con for y sum():
#   print(sum(range(101)))   → 5050  (range(101) genera del 0 al 100)


# =============================================================================
# EJEMPLO 5: SALUDAR USUARIOS HASTA QUE NO SE INTRODUZCA NOMBRE
# =============================================================================
# El bucle se repite mientras el usuario introduzca un nombre.
# Si pulsa Enter sin escribir nada, el programa termina.
#
# Interacción esperada:
#   Dime tu nombre (pulsa enter sin poner nada para salir)
#   Tu nombre: Ana
#   Hola Ana
#   Tu nombre: Luis
#   Hola Luis
#   Tu nombre:          ← el usuario pulsa Enter sin escribir
#   (el programa termina)
# =============================================================================

print("Dime tu nombre (pulsa enter sin poner nada para salir)")
# Mensaje informativo para que el usuario sepa cómo funciona el programa.

nombre = input("Tu nombre: ")
# Pedimos el nombre ANTES del bucle para poder comprobar la condición.
# Si lo pidiéramos dentro del bucle, no podríamos comprobar el primer valor.
# Si el usuario pulsa Enter sin escribir nada, nombre será "" (cadena vacía).

while nombre != "":
    # El bucle continúa MIENTRAS nombre sea diferente de "" (cadena vacía).
    # "" es una cadena sin ningún carácter, lo que ocurre al pulsar Enter vacío.
    # ALTERNATIVA equivalente: while nombre:  (una cadena vacía equivale a False)

    print("Hola", nombre)
    # Saludamos al usuario. También podría ser: print(f"Hola {nombre}")

    nombre = input("Tu nombre: ")
    # Volvemos a pedir el nombre al final del bucle para actualizar la condición.
    # Este patrón (pedir antes del while y al final del bucle) es muy común
    # cuando la condición depende de un input del usuario.


# =============================================================================
# EJEMPLO 6A: SUMAR LOS N PRIMEROS NÚMEROS (EL USUARIO ELIGE HASTA DÓNDE)
# =============================================================================
# El usuario indica un límite y sumamos todos los números desde 1 hasta ese límite.
#
# Interacción esperada:
#   Ingrese un numero hasta el que quiere sumar: 10
#   La suma de los 10 primeros números es: 55
# =============================================================================

limite = int(input("Ingrese un numero hasta el que quiere sumar: "))
# El usuario decide hasta qué número se suma.
# int() es necesario para poder usar el valor como límite numérico.

suma = 0
# Acumulador de la suma, siempre inicializado a 0.

contador = 1
# Empezamos en 1 porque queremos sumar los números POSITIVOS hasta el límite.
# Si el límite fuera 5: sumaríamos 1+2+3+4+5 = 15.

while contador <= limite:
    # El bucle avanza mientras el contador no supere el límite elegido.

    suma = suma + contador
    # Acumulamos el valor actual del contador en la suma.

    contador = contador + 1
    # Avanzamos al siguiente número.

print(f"La suma de los {limite} primeros números es: {suma}")
# Mostramos el resultado final con el límite y la suma obtenida.
# RETO: prueba con limite=100, ¿obtienes 5050 igual que en el ejemplo 4?


# =============================================================================
# EJEMPLO 6B: SUMAR NÚMEROS INTRODUCIDOS POR EL USUARIO (0 PARA TERMINAR)
# =============================================================================
# El usuario va introduciendo números uno a uno y los vamos sumando.
# Cuando introduce 0, el bucle termina y mostramos la suma total.
# El 0 es el "número centinela": su único papel es indicar que queremos parar.
#
# Interacción esperada:
#   ingrese un numero: 5
#   ingrese un numero: 3
#   ingrese un numero: 10
#   ingrese un numero: 0
#   18                ← 5 + 3 + 10 (el 0 no se suma)
# =============================================================================

numero = int(input("ingrese un numero: "))
# Pedimos el primer número antes del bucle para poder evaluarlo en la condición.
# Si lo pidiéramos dentro, no podríamos comprobar si es 0 antes de la primera vuelta.

suma = 0
# Acumulador que irá guardando la suma de todos los números introducidos.

while numero != 0:
    # El bucle continúa MIENTRAS el número introducido sea distinto de 0.
    # En cuanto el usuario escriba 0, el bucle termina SIN sumar ese 0.
    # Por eso el 0 no aparece en la suma: la condición se comprueba antes de sumar.

    suma = suma + numero
    # Añadimos el número actual a la suma acumulada.
    # Solo llegamos aquí si numero != 0, así que el 0 nunca se suma.

    numero = int(input("ingrese un numero: "))
    # Pedimos el siguiente número. Si el usuario introduce 0 aquí,
    # la próxima comprobación del while será False y el bucle terminará.

print(suma)
# Mostramos la suma total de todos los números introducidos (sin contar el 0).
# MEJORA: print(f"La suma total es: {suma}")
#
# RETO: modifica el programa para que también muestre cuántos números
# introdujo el usuario y cuál es la media.

Repaso if con funciones

# IF: si se cumple una condición hacemos algo y si no, otra cosa

edad=20  # Declaramos una variable entera. También podríamos pedirla al usuario: edad = int(input("¿Cuántos años tienes? "))

if edad>=18:               # Comprobamos si edad es mayor O IGUAL a 18
    print("Mayor de edad") # Si la condición es True, ejecutamos este bloque (está indentado con 4 espacios)
else:                      # Si la condición es False, ejecutamos el bloque alternativo
    print("Menor de edad") # Solo se ejecuta UNO de los dos bloques, nunca los dos

# -----------------------------------------------------------------------

# elif: si no se cumple una condición hacemos otra comprobación todas las veces que queramos
# Ideal para rangos

temperatura=25  # Prueba a cambiar este valor para ver cómo cambia el resultado

if temperatura<=0:          # Primera comprobación. Si es True, entra aquí y SALTA todos los demás
    print("Me congelo")
elif temperatura<=15:       # Solo se comprueba si la anterior fue False
    print("Hace frío")      # Aquí ya sabemos implícitamente que temperatura > 0
elif temperatura<=25:       # Solo se comprueba si todas las anteriores fueron False
    print("¡Que buen tiempo")
elif temperatura<=35:       # Podríamos añadir tantos elif como rangos necesitemos
    print("El caloret")
else:                       # Captura cualquier caso que no haya entrado en ningún if/elif anterior
    print("Me asfixio")     # Con temperatura=25, entrará en el tercer elif (<=25)

# -----------------------------------------------------------------------
# ALTERNATIVA con ifs independientes (sin elif):
# Diferencia clave: aquí se evalúan TODAS las condiciones siempre,
# aunque ya hayamos encontrado una verdadera. Es menos eficiente.
# Por eso cuando los casos son excluyentes, es mejor usar elif.

if temperatura<=0:
    print("Me congelo")
if temperatura>0 and temperatura<=15:   # Necesitamos indicar el límite inferior porque no hay elif
    print("Hace frío")                  # "and" significa que las DOS condiciones deben ser True
if temperatura>15 and temperatura<=25:  # Equivalente más compacto: if 15 < temperatura <= 25
    print("Que buen tiempo")
if temperatura>25 and temperatura<=35:
    print("El caloret")
if temperatura>35:
    print("Me asfixio")

# -----------------------------------------------------------------------

# función mayor a la que le pasamos dos números y nos devuelve el mayor
# mayor(1,2)->2  mayor(8,3)->8
# PASOS
# Defino la función y los parámetros
# Utilizo una variable para el resultado
# Hago el proceso de la función
# Devuelvo el resultado

def mayor(num1,num2):  # "def" define la función. num1 y num2 son parámetros (valores de entrada)
    resultado=0        # Inicializamos la variable de resultado. Buena práctica antes de usarla.
    if num1>num2:      # Comparamos los dos parámetros
        resultado=num1 # Si num1 es mayor, guardamos num1
    else:
        resultado=num2 # Si no, guardamos num2 (incluye el caso en que sean iguales)
    return resultado   # "return" devuelve el valor al lugar donde se llamó la función
                       # ALTERNATIVA más corta: return num1 if num1 > num2 else num2
                       # ALTERNATIVA con max(): return max(num1, num2)

print(mayor(1,2))  # Llamamos a la función con 1 y 2 → devuelve 2
print(mayor(8,3))  # Llamamos con 8 y 3 → devuelve 8
print(mayor(6,9))  # Llamamos con 6 y 9 → devuelve 9

# -----------------------------------------------------------------------

a=int(input("Ingrese el primer número (0 para salir) "))  # int() convierte el texto del input a número entero
b=int(input("Ingrese el segundo número "))                # Si el usuario escribe letras, dará error (pruébalo)

while a!=0:  # Bucle que se repite MIENTRAS a sea distinto de 0. Si el usuario escribe 0, el bucle termina.
    print(f"El mayor de {a} y {b} es {mayor(a,b)}")   # f-string: las variables entre {} se sustituyen por su valor
    a = int(input("Ingrese el primer número (0 para salir)")) # Pedimos de nuevo para poder volver a comprobar el while
    b = int(input("Ingrese el segundo número"))               # Importante: si no actualizamos a, el bucle sería infinito

# -----------------------------------------------------------------------

# Vamos a crear una función cadena_mas_corta a la que le pasamos dos cadenas
# y nos devuelve la más corta
# cadena_mas_corta("Eva","María")->"Eva"

def cadena_mas_corta(cadena1,cadena2):
    resultado=cadena1       # Asumimos que la primera cadena es la más corta (valor por defecto)

    if len(cadena1)>len(cadena2):  # len() devuelve el número de caracteres de una cadena
        resultado=cadena2          # Si cadena1 es MÁS LARGA, entonces cadena2 es la más corta
    # Ojo: si tienen la misma longitud, devuelve cadena1 (la asignada por defecto al inicio)
    # ALTERNATIVA más corta: return cadena1 if len(cadena1) <= len(cadena2) else cadena2
    # ALTERNATIVA con min(): return min(cadena1, cadena2, key=len)

    return resultado  # Devolvemos la cadena más corta

print(cadena_mas_corta("Eva","María"))                           # "Eva" tiene 3 letras, "María" tiene 5 → devuelve "Eva"
print(cadena_mas_corta("otorrinolaringólogo","patata"))          # "patata" es más corta → devuelve "patata"
print(cadena_mas_corta("alubias","supercalifragilísticoespialidoso")) # "alubias" es más corta → devuelve "alubias"

Explicación irpf con return

# ============================================================
# CALCULADORA DE IRPF (Impuesto sobre la Renta de las Personas Físicas)
# ============================================================
# El IRPF es un porcentaje que se descuenta del sueldo como impuesto.
# Cuanto más ganas, mayor es el porcentaje que pagas.
# ============================================================


# --- DEFINICIÓN DE LA FUNCIÓN ---
# Una función es un bloque de código reutilizable al que le damos un nombre.
# Así no tenemos que repetir el mismo código cada vez que lo necesitemos.
#
# "def" indica que estamos definiendo (creando) una función.
# "calculo_irpf" es el nombre que le damos a la función.
# "(sueldo)" es el parámetro: un valor que la función recibe para trabajar con él.
# Cada vez que llamemos a la función, le pasaremos un sueldo diferente.

def calculo_irpf(sueldo):

    # La función comprueba en qué tramo está el sueldo
    # y devuelve el porcentaje de IRPF correspondiente.
    # "return" significa "devuelve este resultado al código que me llamó".

    if sueldo <= 1000:
        # Si el sueldo es 1000€ o menos → 9% de IRPF
        # En Python, 0.09 equivale al 9% (9 dividido entre 100)
        return 0.09

    elif sueldo <= 5000:
        # Si el sueldo está entre 1001€ y 5000€ → 12% de IRPF
        # "elif" significa "si lo anterior no se cumplió, comprueba esto otro"
        return 0.12

    else:
        # Si el sueldo supera los 5000€ → 15% de IRPF
        # "else" significa "en cualquier otro caso"
        return 0.15


# ============================================================
# --- EJEMPLOS DE USO DE LA FUNCIÓN ---
# ============================================================

# EJEMPLO 1: Mostrar directamente el porcentaje de IRPF para 1000€
# Llamamos a la función con sueldo=1000 e imprimimos lo que devuelve.
# Resultado esperado: 0.09 (es decir, el 9%)
print(calculo_irpf(1000))


# EJEMPLO 2: Calcular la cantidad en euros que se paga de IRPF
# Primero obtenemos el porcentaje para 4000€ (será 0.12, el 12%)
# Luego multiplicamos ese porcentaje por el sueldo para saber cuántos euros son.
# 4000 * 0.12 = 480€ de impuesto
# Guardamos el resultado en la variable "irpf" para poder imprimirla después.
irpf = calculo_irpf(4000) * 4000
print(irpf)


# EJEMPLO 3: Calcular el sueldo NETO (lo que realmente cobras)
# Sueldo neto = sueldo bruto - lo que pagas de IRPF
# Para un sueldo de 10000€: 10000 - (0.15 * 10000) = 10000 - 1500 = 8500€
#
# Usamos una f-string para mostrar el resultado con texto.
# Las f-strings empiezan con la letra f antes de las comillas: f"..."
# Todo lo que va dentro de llaves {} se calcula y se muestra como número.
print(f"Sueldo bruto: {10000 - calculo_irpf(10000) * 10000}")


# ============================================================
# --- CÁLCULO PARA UN EMPLEADO CONCRETO ---
# ============================================================

# Guardamos el nombre y el sueldo en variables para trabajar con ellos
empleado = "Ana"
sueldo = 3000

# Calculamos el porcentaje de IRPF que le corresponde a Ana (será 0.12)
irpf = calculo_irpf(sueldo)

# Calculamos su sueldo neto y lo mostramos con una f-string
# sueldo - sueldo * irpf = 3000 - 3000 * 0.12 = 3000 - 360 = 2640€
print(f"El empleado {empleado} tiene un sueldo de {sueldo} y el sueldo neto es {sueldo - sueldo * irpf}")


# ============================================================
# --- CÁLCULO PARA VARIOS EMPLEADOS CON UN BUCLE ---
# ============================================================

# En lugar de repetir el código para cada persona, usamos listas y un bucle.

# Una lista es una colección de valores entre corchetes [], separados por comas.
# Aquí guardamos los nombres de los empleados en orden.
empleados = ["Ana", "Eva", "Iu", "Pep"]

# Otra lista con los sueldos, en el mismo orden que los nombres.
# empleados[0]="Ana" corresponde a sueldos[0]=3000, etc.
sueldos = [3000, 18000, 900, 4000]

# "for" crea un bucle: repite el bloque de código varias veces.
# "range(len(empleados))" genera los números 0, 1, 2, 3
#   - len(empleados) cuenta cuántos elementos hay en la lista (4 en este caso)
#   - range(4) produce la secuencia: 0, 1, 2, 3
# En cada vuelta del bucle, "i" toma uno de esos valores (0, 1, 2, 3)
# y lo usamos como índice para acceder al empleado y sueldo correspondiente.
for i in range(len(empleados)):

    # empleados[i] → el nombre del empleado en la posición i
    # sueldos[i]   → el sueldo del empleado en la posición i
    # calculo_irpf(sueldos[i]) → el porcentaje de IRPF según su sueldo
    # sueldos[i] - sueldos[i] * calculo_irpf(sueldos[i]) → su sueldo neto

    print(f"El empleado {empleados[i]} tiene un sueldo de {sueldos[i]} "
          f"y el sueldo neto es {sueldos[i] - sueldos[i] * calculo_irpf(sueldos[i])}")

# Resultado del bucle:
# i=0 → Ana,  3000€  → 3000  - 3000  * 0.12 = 2640.0€
# i=1 → Eva,  18000€ → 18000 - 18000 * 0.15 = 15300.0€
# i=2 → Iu,   900€   → 900   - 900   * 0.09 = 819.0€
# i=3 → Pep,  4000€  → 4000  - 4000  * 0.12 = 3520.0€

Funciones

# Definimos una función llamada "saludo".
# Una función es un bloque de código que podemos reutilizar cuantas veces queramos.
# La palabra "def" le dice a Python que vamos a definir (crear) una función.
# Los paréntesis () vacíos significan que esta función no necesita ningún dato de entrada.
# Los dos puntos ":" al final son obligatorios — indican que empieza el cuerpo de la función.
def saludo():
    # El código dentro de la función va con sangría (4 espacios).
    # Esto le dice a Python que esta línea pertenece a la función.
    print("Hola")
 
# Aquí "llamamos" a la función por su nombre seguido de ().
# Sin esta línea, la función existe pero nunca se ejecuta.
# Resultado: imprime "Hola"
saludo()
 
# Podemos llamarla tantas veces como queramos sin repetir el código.
# Resultado: imprime "Hola" otra vez
saludo()


# Ahora la función recibe un "parámetro" llamado "nombre".
# Un parámetro es como una variable especial que recibe un valor cuando llamamos la función.
# La "f" antes de las comillas indica un "f-string": permite meter variables dentro del texto
# usando llaves {}. Aquí {nombre} se sustituirá por el valor recibido.
def saludo_personal(nombre):
    print(f"Hola {nombre} ¿Qué tal estás?")
 
# Al llamar la función, le pasamos el valor "Ana".
# Dentro de la función, "nombre" valdrá "Ana". Resultado: "Hola Ana ¿Qué tal estás?"
saludo_personal("Ana")
 
# La misma función, pero ahora "nombre" valdrá "Pep". Resultado: "Hola Pep ¿Qué tal estás?"
saludo_personal("Pep")

# Esta función recibe DOS parámetros: "nombre" y "edad".
# Dentro usamos un "if/else" para tomar decisiones según el valor de "edad".
def portero_discoteca(nombre, edad):
    # Si "edad" es mayor o igual a 18, entra.
    if edad >= 18:
        print(f"Adelante, {nombre}, disfruta de la fiesta")
    # En cualquier otro caso (edad < 18), no entra.
    else:
        print(f"Lo siento, {nombre}, no puedes entrar")
 
# Ana tiene exactamente 18: entra (>= incluye el 18).
portero_discoteca("Ana", 18)
# Pep tiene 16: no entra.
portero_discoteca("Pep", 16)
# José Luis tiene 116: entra igualmente, porque 116 >= 18.
portero_discoteca("José Luis", 116)
# El parámetro "nombres" recibirá una lista (varios valores entre corchetes []).
# El bucle "for" recorre la lista uno a uno, guardando cada elemento en "nombre".
def saludo_multiple(nombres):
    for nombre in nombres:
        print(f"Hola, {nombre}")
 
# Pasamos la lista directamente. Imprime: "Hola, Ana", "Hola, Pep", "Hola, Eva".
saludo_multiple(["Ana", "Pep", "Eva"])
 
# También podemos guardar la lista en una variable primero y luego pasarla.
# Resultado idéntico: la función no sabe si recibe una lista directa o una variable.
alumnos = ["Iu", "Rosa", "Juan"]
saludo_multiple(alumnos)
 
# La función no sabe que esto son flores, solo ve una lista de textos.
# Resultado: "Hola, Rosa", "Hola, Jazmín", "Hola, Crisantemo".
flores = ["Rosa", "Jazmín", "Crisantemo"]
saludo_multiple(flores)
 
# Una lista con un solo elemento sigue siendo una lista.
# Resultado: "Hola, pEPE" (respeta mayúsculas y minúsculas tal cual).
saludo_multiple(["pEPE"])
# Esta función dibuja un "arbolito" de asteriscos.
# Usamos un bucle "while" (mientras) en lugar de "for".
# "while" repite el bloque MIENTRAS la condición sea verdadera.
def arbolito(tamanyo):
    # "contador" empieza en 0. Es la variable que controla cuántas veces repetimos.
    contador = 0
    # El bucle continúa mientras "contador" sea menor o igual que "tamanyo".
    while contador <= tamanyo:
        # "*" * contador repite el carácter "*" tantas veces como indica "contador".
        # Con contador=0 imprime "" (nada), con 1 imprime "*", con 2 "**", etc.
        print("*" * contador)
        # ¡Muy importante! Aumentamos el contador en 1 en cada vuelta.
        # Sin esta línea, el bucle nunca terminaría (bucle infinito).
        contador += 1
 
# Imprime líneas con 0, 1, 2, 3, 4 y 5 asteriscos.
arbolito(5)
# Imprime líneas con 0, 1, 2 y 3 asteriscos.
arbolito(3)
# Hasta ahora las funciones solo imprimían. Esta función DEVUELVE un resultado con "return".
# El valor devuelto puede guardarse en una variable o usarse en una expresión.
def doble(numero):
    return numero * 2
 
# La función calcula 5*2=10 y lo devuelve... pero nadie lo recoge. No pasa nada visible.
doble(5)  # Esto no hace nada
 
# Ahora sí: pasamos el valor devuelto directamente a print(). Imprime: 10.
print(doble(5))  # Esto imprime 10
 
# También podemos guardar el resultado en una variable para usarlo más tarde.
resultado = doble(5)  # resultado vale 10
 
# Esta versión usa print() dentro en lugar de return.
# Imprime el resultado, pero NO lo devuelve: no podemos guardarlo en una variable.
def doble_sin_return(numero):
    print(numero * 2)
 
# Imprime 10, pero no podemos hacer resultado = doble_sin_return(5) de forma útil.
doble_sin_return(5)
# Esta función comprueba si un número es par y devuelve True (verdadero) o False (falso).
# El operador "%" calcula el RESTO de una división. Si numero % 2 == 0, es divisible entre 2.
def es_par(numero):
    if numero % 2 == 0:  # 14 % 2 = 0 → es par
        return True
    else:
        return False
 
# Guardamos el número en una variable para mayor claridad.
numero = 14
# "if es_par(numero)" equivale a "if True" cuando el número es par.
# La función devuelve True/False directamente, así que podemos usarla en el if.
if es_par(numero):
    print("Es par")
else:
    print("Es impar")

Iteración de listas

# ─────────────────────────────────────────────
# DESCRIPCIÓN GENERAL DEL PROGRAMA
# ─────────────────────────────────────────────
# Este programa practica las operaciones más habituales sobre listas:
# - Encontrar el número más pequeño de una lista.
# - Encontrar el mayor y el menor
# - Dado un número, indica si está en la lista.
# - Añadido: contar cuantas veces aparece
# - Cuenta cuántas veces aparece cada número.

# La lista de trabajo. Contiene 20 números, algunos repetidos (3, -2, 7, 0)
# y algunos negativos. Todos los ejercicios trabajan sobre esta misma lista.
lista=[3, -2, 7, 0, 10, -5, 4, 8, -1, 6, 2, -3, 9, 1, -4, 5, 7, 0, 3, -2]


# ─────────────────────────────────────────────
# BLOQUE 1: Encontrar el mayor y el menor
# ─────────────────────────────────────────────

# Partimos de que el primer elemento es tanto el menor como el mayor provisional.
# lista[0] accede al primer elemento de la lista, que es el 3.
# Conforme recorramos la lista iremos actualizando estos valores si encontramos
# algo más pequeño o más grande.
menor=lista[0]
mayor=lista[0]

# Recorro la lista  ← comentario original
# En cada vuelta 'numero' toma el valor del siguiente elemento de la lista.
for numero in lista:

    # Si el número actual es menor que el menor que llevamos hasta ahora,
    # actualizamos el menor. Así al final de la lista menor tendrá el mínimo real.
    if numero<menor:
        menor=numero

    # Mismo patrón pero para el mayor.
    # Usamos dos if separados (no elif) porque queremos comparar ambas condiciones
    # en cada vuelta, aunque en la práctica un número nunca puede ser a la vez
    # mayor Y menor que el provisional.
    if numero>mayor:
        mayor=numero

# Imprimimos nuestro resultado y lo comparamos con las funciones built-in de Python.
# min(lista) y max(lista) hacen exactamente lo mismo que nuestro bucle pero en una línea.
# Si ambas columnas coinciden, nuestro algoritmo es correcto.
print(menor,min(lista))   # Resultado: -5 -5
print(mayor,max(lista))   # Resultado: 10 10

# Sugerencia: en la práctica siempre usarías min() y max() directamente.
# Hacer el bucle a mano sirve para entender cómo funcionan por dentro.


# ─────────────────────────────────────────────
# BLOQUE 2: Buscar si un número está en la lista
# ─────────────────────────────────────────────

# Dado un número, indica si está en la lista.  ← comentario original

# El número que queremos encontrar.
# Cambia este valor para buscar cualquier otro número.
buscado=9 # Número a buscar

# La bandera (flag) empieza en False.
# Se convertirá en True solo si encontramos el número.
encontrado=False

for numero in lista:
    if numero==buscado:
        encontrado=True
        # break interrumpe el bucle inmediatamente en cuanto encuentra el número.
        # No tiene sentido seguir recorriendo el resto de la lista si ya lo encontramos.
        # Sin el break el bucle seguiría hasta el final aunque ya supiera la respuesta.
        break

# Este if está FUERA del bucle. Se ejecuta una sola vez cuando el bucle ha terminado.
# En ese momento encontrado es True (si lo encontró) o False (si recorrió todo sin éxito).
if encontrado:
    print("Encontrado")
else:
    print("No encontrado")
# Resultado: Encontrado  (el 9 sí está en la lista, en la posición 12)

# Sugerencia: Python tiene una forma más corta de hacer esto sin bucle ni bandera:
#   if buscado in lista:
#       print("Encontrado")
# El operador 'in' hace la búsqueda por nosotros. Lo veremos más adelante en el código.


# ─────────────────────────────────────────────
# BLOQUE 3: Contar cuántas veces aparece un número concreto
# ─────────────────────────────────────────────

# Añadido: contar cuantas veces aparece  ← comentario original

# Ahora buscamos el 3. Fíjate que hay DOS 3 en la lista (posiciones 0 y 18).
buscado=3

# El contador acumulador empieza en 0.
# Cada vez que encontremos el número buscado, sumamos 1.
contador=0

for numero in lista:
    if numero==buscado:
        contador+=1   # equivale a: contador = contador + 1
                      # Aquí NO usamos break porque queremos contar TODAS las apariciones,
                      # no solo la primera. El bucle recorre la lista entera.

print(f"El número {buscado} aparece {contador} veces")
# Resultado: El número 3 aparece 2 veces

# Sugerencia: Python tiene el método count() que hace lo mismo en una línea:
#   print(lista.count(3))   → 2


# ─────────────────────────────────────────────
# BLOQUE 4: Contar cuántas veces aparece CADA número (con bucles anidados)
# ─────────────────────────────────────────────

# Cuenta cuántas veces aparece cada número.  ← comentario original

# Esta línea está comentada, es una lista de prueba más pequeña que el autor usó
# para verificar el comportamiento antes de aplicarlo a la lista grande.
#lista=[1,2,2,4]

# Bucle exterior: recorre cada número de la lista como "el buscado del momento".
# En cada vuelta buscado toma un valor de la lista: 3, luego -2, luego 7...
for buscado in lista:

    # El contador se reinicia a 0 en cada vuelta del exterior.
    # Esto es fundamental: si no lo reiniciáramos, el contador seguiría acumulando
    # de una búsqueda a la siguiente y los resultados serían incorrectos.
    contador = 0

    # Bucle interior: recorre TODA la lista buscando el número actual.
    # Por cada vuelta del exterior, el interior da 20 vueltas (tamaño de la lista).
    # Total de comparaciones: 20 × 20 = 400 comparaciones en total.
    for numero in lista:
        if numero == buscado:
            contador += 1

    # Este print está dentro del exterior pero fuera del interior.
    # Se ejecuta una vez por cada número buscado.
    print(f"El número {buscado} aparece {contador} veces")

# Resultado: imprime 20 líneas, una por cada elemento.
# Los repetidos aparecen varias veces: el 3 aparece dos veces en el resultado
# (una cuando buscado=3 la primera vez y otra cuando buscado=3 la segunda vez).
# Esto se mejorará en el último bloque usando una lista sin repetidos.

# Sugerencia: existe una estructura llamada diccionario (dict) que es perfecta
# para este tipo de conteos, pero eso es un tema más avanzado.


# ─────────────────────────────────────────────
# BLOQUE 5: Separar pares e impares con append
# ─────────────────────────────────────────────

# para añadir elementos a una lista usamos append  ← comentario original
# append(elemento) añade un elemento al FINAL de una lista existente.

# Dos listas vacías que iremos llenando dentro del bucle.
# Empiezan vacías [] y crecen con cada append.
pares=[]
impares=[]

for numero in lista:

    # numero%2 es el resto de dividir numero entre 2.
    # Si el resto es 0 el número es par (4%2=0, 6%2=0, 0%2=0).
    # Si el resto es 1 (o -1 para negativos) el número es impar.
    if numero%2==0:
        pares.append(numero)    # añade numero al final de la lista pares

    else:
        impares.append(numero)  # añade numero al final de la lista impares

# Los print están FUERA del bucle: muestran las listas completas al terminar.
print(f"Pares: {pares}")
print(f"Impares: {impares}")
# Resultado:
# Pares: [-2, 0, 10, 4, 8, 6, 2, 0, -2]  (divisibles entre 2, incluido el 0)
# Impares: [3, 7, -5, -1, -3, 9, 1, -4, 5, 7, 3]

# Sugerencia: Python tiene una forma compacta llamada comprensión de lista:
#   pares = [n for n in lista if n % 2 == 0]
# Pero usar append con el bucle es más claro cuando se está aprendiendo.


# ─────────────────────────────────────────────
# BLOQUE 6: Separar positivos y negativos
# ─────────────────────────────────────────────

# Con la otra lista separar entre positivos y negativos. El 0 lo ponemos en positivos
# ← comentario original. La decisión de incluir el 0 en positivos es arbitraria
# y se refleja en la condición: >= 0 en lugar de > 0.

positivos=[]
negativos=[]

for numero in lista:

    # El 0 entra aquí porque 0 >= 0 es True.
    # Si quisiéramos el 0 en negativos cambiaríamos >= por >.
    if numero>=0:
        positivos.append(numero)
    else:
        negativos.append(numero)

# len() devuelve el número de elementos que tiene una lista.
# len(positivos) nos dice cuántos números positivos (incluido el 0) hay.
print(f"Positivos: {positivos} y tiene {len(positivos)} elementos")
print(f"Negativos: {negativos}")
# Resultado:
# Positivos: [3, 7, 0, 10, 4, 8, 6, 2, 9, 1, 5, 7, 0, 3] y tiene 14 elementos
# Negativos: [-2, -5, -1, -3, -4, -2]


# ─────────────────────────────────────────────
# BLOQUE 7: Comprobar si un elemento está en una lista con 'in'
# ─────────────────────────────────────────────

# Como sabe si un elemento está en una lista  ← comentario original
# Este bloque muestra la forma corta de buscar, sin necesidad de bucle ni bandera.

buscado=34

# El operador 'in' recorre la lista internamente y devuelve True o False.
# Es equivalente al bucle con bandera del bloque 2, pero en una sola palabra.
# Si el 34 estuviera en la lista, entraría por el if. Como no está, entra por el else.
if buscado in lista:
    print(f"{buscado} está en lista")
else:
    print(f"{buscado} NO está en lista")
# Resultado: 34 NO está en lista

# 'not in' es el contrario: devuelve True si el elemento NO está en la lista.
# Ejemplo:
#   if buscado not in lista:
#       print("No está")


# ─────────────────────────────────────────────
# BLOQUE 8: Eliminar repetidos y contar apariciones de forma limpia
# ─────────────────────────────────────────────

# Redefinimos la lista con una más pequeña y con repetidos evidentes para ver mejor el resultado.
# Esta asignación sobreescribe la lista original del principio del programa.
lista=[1,2,2,4,1,4,9]

# Lista auxiliar donde guardaremos solo los valores únicos (sin repetidos).
# Iremos añadiendo números uno a uno, pero solo si no están ya dentro.
sin_repetidos=[]

for numero in lista:

    # 'not in' comprueba si numero NO está ya en sin_repetidos.
    # Si no está → lo añadimos. Si ya está → lo ignoramos (no entra en el if).
    # Traza con la lista [1,2,2,4,1,4,9]:
    # numero=1: sin_repetidos=[]       → 1 no está → añadimos → [1]
    # numero=2: sin_repetidos=[1]      → 2 no está → añadimos → [1,2]
    # numero=2: sin_repetidos=[1,2]    → 2 SÍ está → ignoramos → [1,2]
    # numero=4: sin_repetidos=[1,2]    → 4 no está → añadimos → [1,2,4]
    # numero=1: sin_repetidos=[1,2,4]  → 1 SÍ está → ignoramos → [1,2,4]
    # numero=4: sin_repetidos=[1,2,4]  → 4 SÍ está → ignoramos → [1,2,4]
    # numero=9: sin_repetidos=[1,2,4]  → 9 no está → añadimos → [1,2,4,9]
    if not numero in sin_repetidos:
        sin_repetidos.append(numero)

# Ahora sin_repetidos = [1, 2, 4, 9] — solo los valores únicos, en orden de aparición.

# Bucle exterior: recorre solo los valores únicos (4 vueltas en vez de 7).
# Así cada número aparece exactamente una vez en el resultado, sin duplicados.
for buscado in sin_repetidos:

    # Reiniciamos el contador en cada valor único buscado.
    contador = 0

    # Bucle interior: recorre la lista ORIGINAL completa (con repetidos)
    # para contar cuántas veces aparece el valor buscado.
    for numero in lista:
        if numero == buscado:
            contador += 1

    # Este print está dentro del exterior pero fuera del interior.
    # Imprime el número y su contador, pero SIN salto de línea al final (end=" ").
    # Así el siguiente print (vez/veces) se imprime en la misma línea.
    print(f"El número {buscado} aparece {contador}", end=" ")

    # Gramática correcta: "1 vez" en singular, "2 veces" en plural.
    # Este if decide qué palabra usar según el valor del contador.
    # Al no tener end=" ", este print sí añade el salto de línea normal al final.
    if contador != 1:
        print("veces")
    else:
        print("vez")

# Resultado final:
# El número 1 aparece 2 veces
# El número 2 aparece 2 veces
# El número 4 aparece 2 veces
# El número 9 aparece 1 vez    ← singular correcto gracias al if de arriba

# Sugerencia: el mismo resultado puede obtenerse con el método count() y sin bucles anidados:
#   for numero in sin_repetidos:
#       veces = lista.count(numero)
#       print(f"El número {numero} aparece {veces} {'vez' if veces == 1 else 'veces'}")
# La expresión 'vez' if veces == 1 else 'veces' es un if de una sola línea (operador ternario).

Explicación anidados

1. Configuración Inicial

Python

limite = 10

Aquí simplemente definimos hasta dónde queremos llegar. El programa hará cálculos para los números del 0 al 9 (porque en programación solemos empezar a contar desde el cero).

2. El Bucle Exterior (El «Contador de Filas»)

Python

for i in range(limite):

Este bucle se encarga de decidir con qué número estamos trabajando en cada momento. Se repetirá 10 veces.

  • En la primera vuelta, i vale 0.

  • En la última, i vale 9.

3. Preparando la Pizarra

Python

    suma = 0
    factorial = 1

¡Ojo aquí! Estas variables se reinician cada vez que el bucle exterior empieza una nueva vuelta.

  • La suma empieza en 0 porque es el elemento neutro de la suma.

  • El factorial empieza en 1 porque si fuera 0, cualquier multiplicación daría siempre 0.

4. El Bucle Interior (El «Calculador»)

Python

    for j in range(i):
        suma = suma + j + 1
        factorial = factorial * (j + 1)

Este es el corazón del código. Se encarga de hacer el trabajo sucio:

    • range(i): Si i vale 3, este bucle interno correrá para j = 0, 1, 2.

    • j + 1: Como j empieza en 0, le sumamos 1 para trabajar con números naturales (1, 2, 3…).

    • Suma: Va acumulando los números (1 + 2 + 3…).

    • Factorial: Va multiplicando los números (1 *2 * 3…).

Shutterstock
Explorar

5. El Resultado

Python

    print(f"{i}: {suma}, {factorial}")

Finalmente, el programa imprime una línea por cada valor de i, mostrándote cómo quedaron la suma y el factorial acumulados.

Ejemplo de lo que verías en pantalla:

i (Número) Suma (1 hasta i) Factorial (1 hasta i)
0 0 1
1 1 1
2 3 (1+2) 2 (1* 2)
3 6 (1+2+3) 6 (1* 2* 3)
4 10 (1+2+3+4) 24 (1* 2*t 3* 4)

Nota para principiantes: Fíjate que cuando i es 0, el bucle interior range(0) no se ejecuta ninguna vez, por eso la suma se queda en 0 y el factorial en 1.

Bucles anidados

# ─────────────────────────────────────────────
# BLOQUE 0: Código comentado (desactivado)
# ─────────────────────────────────────────────

# Las líneas que empiezan con # son comentarios y Python las ignora.
# Este bloque está "apagado" a propósito para que no se ejecute.
# Es un ejemplo sencillo de bucles anidados que el autor dejó como referencia.
# Si quitas los # de cada línea verás cómo funciona:
# El exterior (i) daría dos vueltas: i=1 e i=2
# El interior (j) daría tres vueltas por cada vuelta del exterior: j=1, j=2, j=3
# Total de líneas impresas: 2 × 3 = 6
# Resultado si lo activaras:
#   1 1
#   1 2
#   1 3
#   2 1
#   2 2
#   2 3

# for i in range(1,3):
#     for j in range(1,4):
#         print(i,j)


# ─────────────────────────────────────────────
# BLOQUE 1: Tablas de multiplicar del 1 al 10
# ─────────────────────────────────────────────

# Bucle exterior: recorre los números del 1 al 10.
# En cada vuelta, 'numero' es la tabla que estamos calculando (1, 2, 3... 10).
# range(1,11) genera del 1 al 10 — el 11 no se incluye nunca en range.
for numero in range(1,11):

    # Mostramos el encabezado de cada tabla.
    # \n dentro de una f-string es un salto de línea extra (línea en blanco).
    # Así cada tabla empieza con un poco de espacio visual.
    print(f"Tabla de multiplicar del numero {numero}\n")

    # Bucle interior: recorre los multiplicadores del 1 al 10.
    # Se ejecuta completo (10 vueltas) por cada vuelta del exterior.
    # Total de multiplicaciones: 10 tablas × 10 líneas = 100 líneas en total.
    for i in range(1,11):

        # Imprimimos la operación y su resultado.
        # i*numero calcula el resultado directamente dentro de la f-string.
        # Ejemplo cuando numero=3 e i=4: "4 x 3 = 12"
        print(f"{i} x {numero} = {i*numero}")

    # Esta línea está DENTRO del exterior pero FUERA del interior.
    # Se ejecuta UNA VEZ al terminar cada tabla, dibujando una línea separadora.
    # "="*50 repite el carácter "=" 50 veces seguidas: ==================================================
    print("="*50)


# ─────────────────────────────────────────────
# BLOQUE 2: Combinaciones de tallas y colores
# ─────────────────────────────────────────────

# Dos listas con los valores de cada dimensión.
# El objetivo es generar todas las combinaciones posibles: 3 colores × 4 tallas = 12 combinaciones.
tallas=["S","M","L","XL"]
colores=["verde","azul","amarillo"]

# Bucle exterior: recorre los colores (3 vueltas en total).
for color in colores:

    # Bucle interior: recorre las tallas (4 vueltas por cada color).
    # Por cada color se generan las 4 tallas posibles.
    for talla in tallas:

        # Imprimimos la combinación actual.
        # Ejemplo: "verde | S", "verde | M", "verde | L", "verde | XL"
        # Luego pasará a "azul | S", "azul | M"... y así con cada color.
        print(f"{color} | {talla}")

# Traza completa de las combinaciones generadas:
# verde | S      verde | M      verde | L      verde | XL
# azul | S       azul | M       azul | L        azul | XL
# amarillo | S   amarillo | M   amarillo | L     amarillo | XL

# Sugerencia: si quisieras el orden inverso (primero tallas, luego colores)
# solo habría que intercambiar los dos bucles:
#   for talla in tallas:
#       for color in colores:
#           print(f"{color} | {talla}")

# Línea en blanco para separar visualmente el siguiente bloque.
# \n dentro del print añade un salto de línea extra además del salto normal.
print("\n")


# ─────────────────────────────────────────────
# BLOQUE 3: Cuadrícula de # con bucles anidados (versión 1)
# ─────────────────────────────────────────────

# Dibujamos una cuadrícula de 5×5 usando dos bucles anidados.
# El exterior controla las filas (5 filas).
# El interior controla las columnas (5 columnas por fila).
for filas in range(5):       # filas toma los valores 0, 1, 2, 3, 4

    for columnas in range(5):  # columnas toma los valores 0, 1, 2, 3, 4

        # end=" " es un parámetro de print que cambia el carácter final.
        # Por defecto print termina con \n (salto de línea).
        # Con end=" " termina con un espacio, así los # se imprimen en la MISMA línea.
        # Resultado de las 5 vueltas del interior: " #  #  #  #  # "
        print(" #",end=" ")

    # Este print está DENTRO del exterior pero FUERA del interior.
    # Se ejecuta una vez al terminar cada fila.
    # \n añade una línea en blanco entre filas para que la cuadrícula respire.
    print("\n")

# Resultado visual:
#  #  #  #  #  #
#
#  #  #  #  #  #
#
#  #  #  #  #  #  ... (5 filas)


# ─────────────────────────────────────────────
# BLOQUE 4: Cuadrícula de # sin bucle interior (versión 2, más compacta)
# ─────────────────────────────────────────────

# Esta versión consigue el mismo resultado visual pero con un solo bucle.
# " # "*5 repite la cadena " # " cinco veces: " #  #  #  #  # "
# Es equivalente al bucle interior del bloque anterior pero en una sola línea.
for filas in range(5):
    print(" # "*5)

# Resultado: 5 filas de " #  #  #  #  # "
# La diferencia con el bloque anterior es que aquí no hay línea en blanco entre filas
# porque no tiene el print("\n") extra.

# Conclusión: el bloque 3 y el bloque 4 hacen casi lo mismo.
# El bloque 3 usa dos bucles (más flexible si quisieras cambiar algo en cada celda).
# El bloque 4 usa multiplicación de cadena (más corto y elegante para casos simples).
# Sugerencia: si quisieras una cuadrícula de tamaño variable con el bloque 4:
#   tamanyo = 7
#   for filas in range(tamanyo):
#       print(" # " * tamanyo)


# ─────────────────────────────────────────────
# BLOQUE 5: Tablero de ajedrez con emojis
# ─────────────────────────────────────────────

# Definimos el tamaño del tablero. Con 8 obtenemos un tablero 8×8 como el ajedrez real.
# Cambiando este valor obtenemos tableros de cualquier tamaño sin tocar el resto del código.
tamanyo=8

# Bucle exterior: recorre las filas (0, 1, 2... 7).
for filas in range(tamanyo):

    # Bucle interior: recorre las columnas (0, 1, 2... 7).
    for columnas in range(tamanyo):

        # El truco del tablero está en la suma filas+columnas.
        # Cuando la suma es PAR  (resto 0 al dividir entre 2) → casilla negra ⬛
        # Cuando la suma es IMPAR (resto 1 al dividir entre 2) → casilla blanca ⬜
        #
        # Veamos por qué funciona:
        # Fila 0, Col 0: 0+0=0  par   → ⬛   Fila 0, Col 1: 0+1=1  impar → ⬜
        # Fila 0, Col 2: 0+2=2  par   → ⬛   Fila 0, Col 3: 0+3=3  impar → ⬜
        # Fila 1, Col 0: 1+0=1  impar → ⬜   Fila 1, Col 1: 1+1=2  par   → ⬛
        # Los colores se alternan automáticamente tanto en horizontal como en vertical.
        if (filas+columnas)%2==0:
            print("⬛",end="")  # end="" evita el espacio entre emojis para que queden juntos
        else:
            print("⬜",end="")  # end="" igual que arriba

    # Al terminar cada fila (los 8 cuadros) imprimimos una cadena vacía con salto de línea.
    # print("") es equivalente a print() — simplemente baja a la siguiente línea.
    # Sin esta línea, todos los emojis aparecerían en una sola fila larga.
    print("")

# Resultado visual (tablero 8×8):
# ⬛⬜⬛⬜⬛⬜⬛⬜
# ⬜⬛⬜⬛⬜⬛⬜⬛
# ⬛⬜⬛⬜⬛⬜⬛⬜
# ⬜⬛⬜⬛⬜⬛⬜⬛
# ⬛⬜⬛⬜⬛⬜⬛⬜
# ⬜⬛⬜⬛⬜⬛⬜⬛
# ⬛⬜⬛⬜⬛⬜⬛⬜
# ⬜⬛⬜⬛⬜⬛⬜⬛
#
# Sugerencia: prueba a cambiar tamanyo=4 para un tablero más pequeño,
# o intercambia ⬛ y ⬜ para que empiece por blanco en vez de negro.
# También puedes usar "X " y "O " si los emojis no se ven bien en tu entorno.

Explicación del Código

 

1

Declaración de listas
variables · tipos de datos

frutas       = ["uva", "pera", "kiwi"]
alumnos      = ["Ana", "Pep", "Eva", "Iu"]
notas        = [5, 8, 7, 5, 3, 4]
productos    = ["CPU", "RAM", "HDD"]
temperaturas = [23.6, 31.4, 12.3, 6.7, -2.5]
mixta        = ["Ana", 4, "HDD", 13.4, True]

Una lista en Python es una colección ordenada de elementos entre corchetes [ ], separados por comas. Cada lista tiene un nombre (variable) que usaremos después para acceder a ella.

frutas / alumnos / productos

Listas de cadenas de texto (str). Los textos van siempre entre comillas.

notas

Lista de números enteros (int). Sin decimales, sin comillas.

temperaturas

Lista de números decimales (float). Python usa punto como separador decimal.

mixta

Lista con tipos distintos: texto, entero, decimal y booleano. Python lo permite.

Las listas pueden contener cualquier tipo de dato, e incluso mezclarlos. Esto las hace muy flexibles.

2

Bucle for — recorrer frutas
iteración · print

for fruta in frutas:
    print(fruta)

El bucle for recorre todos los elementos de la lista frutas uno por uno. En cada vuelta, la variable fruta toma el valor del elemento actual. El código indentado (sangrado) dentro del bucle se ejecuta en cada iteración.

uva
pera
kiwi
En lugar de fruta podríamos llamar la variable f, item o cualquier nombre. Lo importante es ser descriptivo.
La indentación (los 4 espacios al inicio de print) es obligatoria en Python. Indica qué código pertenece al bucle.

3

Bucle for — recorrer alumnos
mismo patrón, distinta lista

for alumno in alumnos:
    print(alumno)

Exactamente el mismo patrón que el bucle anterior, pero aplicado a la lista alumnos. La variable del bucle ahora se llama alumno, lo que hace el código más legible.

Ana
Pep
Eva
Iu

4

Contar aprobados con if
contador · condicional · acumulador

aprobados = 0                  # Inicializamos el contador a 0
for nota in notas:
    if nota >= 5:               # ¿La nota es mayor o igual a 5?
        aprobados += 1          # Sí → sumamos 1 al contador
print(aprobados)              # Imprimimos el resultado fuera del bucle

Este patrón es un contador: se inicializa una variable a 0 antes del bucle, y dentro se incrementa cuando se cumple una condición. Al terminar el bucle, la variable contiene el total.

aprobados = 0

Siempre hay que inicializar el contador antes del bucle. Si no, Python dará error al intentar sumar.

aprobados += 1

Es una forma corta de escribir aprobados = aprobados + 1. Suma 1 al valor actual.

4
# (notas ≥ 5 son: 5, 8, 7, 5 → 4 aprobados)
Podríamos usar aprobados = aprobados + 1 en lugar de aprobados += 1. Son equivalentes.
El print(aprobados) está fuera del bucle (sin indentación). Si estuviera dentro, imprimiría el valor en cada vuelta, no solo al final.

5

Media de temperaturas + f-string
acumulador · len() · f-string

# Media temperaturas: suma de todas / cantidad

suma = 0                          # Acumulador inicializado a 0
for temperatura in temperaturas:
    suma += temperatura            # Vamos sumando cada temperatura

print(f"la media de las temperaturas es {suma/len(temperaturas)}")

Aquí usamos un acumulador: igual que el contador pero en lugar de sumar 1 sumamos el valor de cada temperatura. Al final dividimos entre el total de elementos para obtener la media.

suma += temperatura

En cada vuelta, añadimos el valor de la temperatura actual a suma. Al acabar, suma contiene el total.

len(temperaturas)

len() devuelve el número de elementos de la lista. Aquí devuelve 5. Así no hay que contar a mano.

f-string: f»texto {expresión}»

La f-string permite incrustar variables o cálculos directamente dentro de un texto. Se escribe poniendo una f antes de las comillas, y las expresiones van entre llaves { }. Aquí calculamos suma/len(temperaturas) directamente dentro del texto.

la media de las temperaturas es 14.3
# (23.6+31.4+12.3+6.7+(-2.5)) / 5 = 71.5 / 5 = 14.3
Podríamos separar el cálculo: media = suma / len(temperaturas) y luego print(f"... {media}"). Más legible para principiantes.
También existe la función sum() integrada: suma = sum(temperaturas) haría lo mismo que el bucle acumulador.

6

Recorrer lista mixta con type()
tipos de datos · introspección

for elemento in mixta:
    print(elemento, type(elemento))

Este bucle recorre la lista mixta que contiene elementos de distintos tipos. La función type() devuelve el tipo de dato de cualquier variable o valor. El print() recibe dos argumentos separados por coma: los imprime en la misma línea separados por un espacio.

Ana <class ‘str’>
4 <class ‘int’>
HDD <class ‘str’>
13.4 <class ‘float’>
True <class ‘bool’>
str

Cadena de texto. Ej: "Ana", "HDD".

int

Número entero (sin decimales). Ej: 4.

float

Número decimal (con punto). Ej: 13.4.

bool

Booleano: solo puede ser True o False.

type() es muy útil para depurar: cuando no sabes qué tipo tiene una variable, ¡pregúntaselo a Python!
Explicación generada como material educativo · Python 3 · Listas, bucles for, condicionales, acumuladores, f-strings

 

Iterar cadenas

# ─────────────────────────────────────────────
# BLOQUE 1: Contar cuántas veces aparece la letra 'a' en una cadena
# ─────────────────────────────────────────────

# La cadena está en mayúsculas. Si buscamos solo "a" minúscula,
# no encontraríamos nada porque "A" y "a" son caracteres distintos para Python.
cadena="HOLA QUE TAL?"

# El contador acumulador empieza en 0 antes del bucle.
# Cada vez que encontremos una 'a' (en cualquier forma) sumaremos 1.
contador =0

# El for recorre la cadena carácter a carácter.
# En cada vuelta, letra toma el valor del siguiente carácter.
for letra in cadena:

    # letra.lower() convierte la letra actual a minúscula SOLO para la comparación,
    # no modifica la cadena original. Así podemos comparar siempre con "a" minúscula
    # sin importar si en la cadena original era "A" o "a".
    # Ejemplos:
    #   "A".lower() → "a"    "H".lower() → "h"    "a".lower() → "a"
    if letra.lower()=="a":
        contador+=1  # encontramos una 'a' (en cualquier forma), sumamos 1

# El print está fuera del bucle: muestra el total al terminar.
print(contador)
# Resultado: 2  (la 'A' de "HOLA" y la 'A' de "TAL")
#
# Alternativa sin bucle usando el método count():
#   total = cadena.lower().count("a")
#   print(total)
# Pero hacerlo con el bucle a mano ayuda a entender cómo funciona count() por dentro.


# ─────────────────────────────────────────────
# BLOQUE 2: Recorrer una cadena con letras y números mezclados
# ─────────────────────────────────────────────

# Una cadena puede contener cualquier tipo de carácter: letras, números, símbolos.
# El for los recorre todos sin distinción, uno a uno.
cadena="DX450"

# En cada vuelta, caracter toma el valor: "D", luego "X", luego "4", "5", "0"
for caracter in cadena:
    print(caracter)

# Resultado:
#   D
#   X
#   4
#   5
#   0
#
# Fíjate en que "4", "5" y "0" son caracteres de texto, no números enteros.
# Para operar matemáticamente con ellos habría que convertirlos con int("4") = 4.


# ─────────────────────────────────────────────
# BLOQUE 3: Invertir una cadena letra a letra
# ─────────────────────────────────────────────

cadena="hola"

# La cadena invertida empieza vacía. La iremos construyendo dentro del bucle.
# Es un acumulador de texto en lugar de un acumulador numérico.
cadena_invertida=""

# El truco está en el orden en que pegamos cada letra nueva.
# En vez de añadir la letra al FINAL (como haríamos normalmente),
# la ponemos al PRINCIPIO: letra + cadena_invertida
# Así cada letra nueva empuja a las anteriores hacia la derecha.
for letra in cadena:
    cadena_invertida=letra+cadena_invertida
    # Traza paso a paso:
    # Vuelta 1: letra="h"  →  cadena_invertida = "h"  + ""    = "h"
    # Vuelta 2: letra="o"  →  cadena_invertida = "o"  + "h"   = "oh"
    # Vuelta 3: letra="l"  →  cadena_invertida = "l"  + "oh"  = "loh"
    # Vuelta 4: letra="a"  →  cadena_invertida = "a"  + "loh" = "aloh"

print(cadena_invertida)
# Resultado: aloh
#
# Alternativa con slicing (atajo de Python para invertir cadenas):
#   print(cadena[::-1])
# El [::-1] significa: recorre la cadena de atrás hacia adelante con paso -1.
# Pero construirlo con el bucle enseña el concepto de concatenación acumulativa.


# ─────────────────────────────────────────────
# BLOQUE 4: Sumar solo los dígitos numéricos de una cadena mixta
# ─────────────────────────────────────────────

# La cadena mezcla letras y números. Solo queremos sumar los dígitos.
cadena="2026J"

# Acumulador numérico que irá sumando los dígitos encontrados.
total=0

for letra in cadena:

    # Los caracteres en Python tienen un orden (orden ASCII/Unicode).
    # Los dígitos "0" al "9" están ordenados consecutivamente en ese sistema,
    # por lo que comparar letra>="0" and letra<="9" es una forma válida de
    # comprobar si un carácter es un dígito numérico.
    # Ejemplos:
    #   "2" >= "0" and "2" <= "9"  →  True   (es un dígito)
    #   "J" >= "0" and "J" <= "9"  →  False  (es una letra)
    #   "6" >= "0" and "6" <= "9"  →  True   (es un dígito)
    if letra>="0" and letra<="9":

        # int(letra) convierte el carácter "2" en el número entero 2.
        # Sin esta conversión estaríamos sumando texto y daría error.
        # Ejemplo: int("2") = 2    int("0") = 0    int("6") = 6
        total=total+int(letra)
        # Traza paso a paso:
        # Vuelta 1: letra="2"  →  es dígito  →  total = 0 + 2 = 2
        # Vuelta 2: letra="0"  →  es dígito  →  total = 2 + 0 = 2
        # Vuelta 3: letra="2"  →  es dígito  →  total = 2 + 2 = 4  (segundo 2 del "2026")
        # Vuelta 4: letra="6"  →  es dígito  →  total = 4 + 6 = 10
        # Vuelta 5: letra="J"  →  NO es dígito → no entra en el if, total no cambia

print(total)
# Resultado: 10  (2 + 0 + 2 + 6 = 10)
#
# Alternativa usando el método isdigit():
#   if letra.isdigit():
#       total = total + int(letra)
# isdigit() devuelve True si el carácter es un dígito, False si no lo es.
# Es más legible que comparar con "0" y "9", pero ambas formas son correctas.


# ─────────────────────────────────────────────
# BLOQUE 5: Separar letras y números de una cadena mixta
# ─────────────────────────────────────────────

# La cadena mezcla letras y números sin ningún orden fijo.
cadena="23GH123JOP"

# Dos acumuladores de texto, uno para letras y otro para números.
# Ambos empiezan vacíos y se irán llenando dentro del bucle.
letras=""
numeros=""

# El for recorre todos los caracteres uno a uno.
for letra in cadena:

    # Usamos la misma comparación del bloque anterior para detectar dígitos.
    # Si el carácter está entre "0" y "9" es un número, si no es una letra.
    if letra>="0" and letra<="9":
        numeros=numeros+letra  # pegamos el dígito al final de la cadena de números
    else:
        letras=letras+letra    # pegamos la letra al final de la cadena de letras

    # Traza paso a paso:
    # Vuelta 1:  letra="2"  →  es dígito  →  numeros="2",      letras=""
    # Vuelta 2:  letra="3"  →  es dígito  →  numeros="23",     letras=""
    # Vuelta 3:  letra="G"  →  NO dígito  →  numeros="23",     letras="G"
    # Vuelta 4:  letra="H"  →  NO dígito  →  numeros="23",     letras="GH"
    # Vuelta 5:  letra="1"  →  es dígito  →  numeros="231",    letras="GH"
    # Vuelta 6:  letra="2"  →  es dígito  →  numeros="2312",   letras="GH"
    # Vuelta 7:  letra="3"  →  es dígito  →  numeros="23123",  letras="GH"
    # Vuelta 8:  letra="J"  →  NO dígito  →  numeros="23123",  letras="GHJ"
    # Vuelta 9:  letra="O"  →  NO dígito  →  numeros="23123",  letras="GHJO"
    # Vuelta 10: letra="P"  →  NO dígito  →  numeros="23123",  letras="GHJOP"

# Ambos print están fuera del bucle: muestran los resultados finales.
print(letras)   # Resultado: GHJOP
print(numeros)  # Resultado: 23123
#
# Fíjate en que los números se guardan como texto ("23123"), no como un entero.
# Si quisiéramos el valor numérico tendríamos que convertirlo: int(numeros) = 23123.
# Si quisiéramos SUMAR los dígitos en lugar de concatenarlos, usaríamos
# total = total + int(letra) como en el bloque anterior.

Ejemplos for con rango

# ─────────────────────────────────────────────
# BLOQUE 1: Recorrer un rango y mostrar cada número
# ─────────────────────────────────────────────

# for con rangos  ← título original del programa

# range(1, 11) genera la secuencia: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
# REGLA IMPORTANTE: el primer número SÍ se incluye, el segundo NO.
# Por eso para llegar al 10 hay que escribir 11 como límite.
# En cada vuelta del bucle, la variable numero toma el valor siguiente de la secuencia.
for numero in range(1,11):
    print(numero)

# Resultado: imprime los números del 1 al 10, cada uno en su línea.
#
# Variaciones de range() que conviene conocer:
#   range(5)         → 0, 1, 2, 3, 4          (un solo argumento: empieza en 0)
#   range(0, 10, 2)  → 0, 2, 4, 6, 8          (tercer argumento: el salto entre números)
#   range(10, 0, -1) → 10, 9, 8, 7... 1       (salto negativo: cuenta hacia atrás)
#   range(0, 100, 5) → 0, 5, 10, 15... 95     (de 5 en 5)


# ─────────────────────────────────────────────
# BLOQUE 2: Sumar todos los números del 1 al 10
# ─────────────────────────────────────────────

# El acumulador es una variable que empieza en 0 ANTES del bucle
# y va sumando valores en cada vuelta.
# Si lo inicializáramos dentro del bucle, se reiniciaría a 0 en cada vuelta
# y nunca acumularía nada. Por eso SIEMPRE se declara fuera.
suma=0

for numero in range(1,11):
    suma+=numero  # es exactamente lo mismo que escribir: suma = suma + numero
                  # Traza paso a paso de cómo crece suma:
                  # Vuelta 1:  suma = 0  + 1  = 1
                  # Vuelta 2:  suma = 1  + 2  = 3
                  # Vuelta 3:  suma = 3  + 3  = 6
                  # Vuelta 4:  suma = 6  + 4  = 10
                  # Vuelta 5:  suma = 10 + 5  = 15
                  # Vuelta 6:  suma = 15 + 6  = 21
                  # Vuelta 7:  suma = 21 + 7  = 28
                  # Vuelta 8:  suma = 28 + 8  = 36
                  # Vuelta 9:  suma = 36 + 9  = 45
                  # Vuelta 10: suma = 45 + 10 = 55

# El print está FUERA del bucle (sin sangría).
# Si estuviera dentro con sangría, imprimiría el subtotal en cada vuelta.
# Al estar fuera, solo imprime el resultado final cuando el bucle ha terminado.
print(suma)
# Resultado: 55
#
# Curiosidad matemática: la fórmula de Gauss da el mismo resultado sin bucle:
#   n * (n+1) / 2  →  10 * 11 / 2 = 55
# Pero construir el bucle a mano es la mejor forma de entender el patrón acumulador.


# ─────────────────────────────────────────────
# BLOQUE 3: Mostrar solo los números pares del 1 al 10
# ─────────────────────────────────────────────

# Este bloque combina un for con un if dentro.
# El for genera todos los números del 1 al 10.
# El if filtra: solo deja pasar los que cumplen la condición.
for numero in range(1,11):

    # El operador % (módulo) devuelve el resto de una división.
    # Si numero % 2 == 0, el resto al dividir entre 2 es cero → el número es par.
    # Ejemplos:  4 % 2 = 0  →  par      5 % 2 = 1  →  impar
    #            6 % 2 = 0  →  par      7 % 2 = 1  →  impar
    if numero % 2 == 0:
        print(numero)

# Resultado: 2  4  6  8  10  (cada uno en su línea)
#
# Para imprimir los IMPARES en su lugar, solo habría que cambiar == 0 por != 0:
#   if numero % 2 != 0:
#       print(numero)
# Resultado: 1  3  5  7  9
#
# Alternativa con range de salto 2 (sin necesidad de if):
#   for numero in range(2, 11, 2):   → genera directamente 2, 4, 6, 8, 10
#       print(numero)


# ─────────────────────────────────────────────
# BLOQUE 4: Dibujar un triángulo de asteriscos
# ─────────────────────────────────────────────

# Este bloque usa una propiedad de Python muy útil:
# multiplicar una cadena de texto por un número la repite ese número de veces.
# Ejemplos:
#   "*" * 1  →  *
#   "*" * 3  →  ***
#   "*" * 5  →  *****
#   "ab" * 3 →  ababab
for numero in range(1,11):
    print("*"*numero)  # en cada vuelta, numero vale 1, 2, 3... 10
                       # así que se imprimen 1, 2, 3... 10 asteriscos seguidos

# Resultado visual (un triángulo que crece):
#   *
#   **
#   ***
#   ****
#   *****
#   ******
#   *******
#   ********
#   *********
#   **********
#
# Para un triángulo invertido (que decrece) bastaría con invertir el range:
#   for numero in range(10, 0, -1):
#       print("*" * numero)
# Resultado: empieza con 10 asteriscos y va bajando hasta 1.


# ─────────────────────────────────────────────
# BLOQUE 5: Tabla de multiplicar de un número
# ─────────────────────────────────────────────

# Tabla de multiplicar  ← comentario original

# El factor es el número del que queremos calcular la tabla.
# Cambiando este valor obtenemos cualquier tabla de multiplicar.
factor=7

# El range va del 1 al 10 (el 11 no se incluye).
# En cada vuelta, numero toma los valores 1, 2, 3... 10.
for numero in range(1,11):

    # La f-string permite construir el texto con las variables directamente.
    # {numero}       → el multiplicador (1, 2, 3... 10)
    # {factor}       → siempre 7
    # {numero*factor}→ el resultado
    print(f"{numero} X {factor} = {numero*factor}")