Serie Fundamentos de Python — Parte 5. Esta publicación continúa la Parte 1: Lo que Todo Principiante Debería Saber, la Parte 2: Variables y Tipos de Datos, la Parte 3: Listas y Diccionarios y la Parte 4: La Sentencia If. Cada publicación de la serie toma un tema y lo explica a fondo. Esta trata sobre la entrada del usuario y los ciclos while.

Hasta ahora, todos los programas de esta serie han trabajado con datos escritos directamente en el código. Eso está bien para aprender, pero los programas reales necesitan interactuar: hacer una pregunta, esperar una respuesta y reaccionar. Una calculadora de cotizaciones necesita saber cuántas páginas quieres. Un cuestionario necesita tus respuestas. Una herramienta de línea de comandos necesita saber qué quieres que haga después.

Ahí entran dos herramientas. La función input() permite que tu programa le pida información al usuario. El ciclo while permite que tu programa siga haciendo algo mientras una condición sea verdadera, como volver a preguntar hasta obtener una respuesta válida, o seguir funcionando hasta que el usuario escriba quit.

En esta publicación aprenderás a obtener datos del usuario, a convertirlos y revisarlos, y a escribir ciclos while que se repitan exactamente lo necesario, sin quedarse funcionando para siempre por accidente.

Ejecuta estos ejemplos como script. Como esperan a que escribas, es más fácil probarlos en un archivo. Guarda el código con un nombre como practice.py y ejecútalo con python3 practice.py en tu terminal.

Obtener Datos con input()

La función input() muestra un mensaje, llamado prompt, espera a que el usuario escriba algo y presione Enter, y luego te devuelve lo que escribió:

name = input("What's your name? ")
print(f"Nice to meet you, {name}!")

Al ejecutarlo, el programa se detiene en el prompt:

What's your name? Maria
Nice to meet you, Maria!

Fíjate en el espacio al final de "What's your name? ". Sin él, la respuesta del usuario aparecería pegada al signo de interrogación.

Para prompts más largos, puedes armar el mensaje primero en una variable:

prompt = "Tell us about your business so we can recommend a package."
prompt += "\nWhat kind of business do you run? "

business = input(prompt)

El \n agrega un salto de línea, así que la pregunta aparece en su propia línea debajo de la explicación.

Limpiar lo que Escribe la Gente

La gente agrega espacios de más y usa mayúsculas sin mucha consistencia. Limpia la respuesta antes de usarla: .strip() quita los espacios de ambos extremos y .lower() la pone en minúsculas para que las comparaciones funcionen:

answer = input("Do you need hosting? (yes/no) ").strip().lower()

if answer == "yes":
    print("We'll include hosting in your quote.")

Ahora "Yes", " YES " y "yes" cuentan como sí.

La Entrada Siempre Es Texto

Esto es lo más importante que debes recordar sobre input(): siempre devuelve una cadena, aunque el usuario escriba un número. Como aprendiste en la Parte 2, no puedes hacer operaciones matemáticas con texto:

pages = input("How many pages do you need? ")   # el usuario escribe 5
print(pages * 2)   # 55: el texto "5" repetido dos veces, ¡no 10!

Convierte la entrada con int() o float() antes de usarla como número:

pages = int(input("How many pages do you need? "))
print(pages * 2)   # 10

Revisar Antes de Convertir

Si el usuario escribe algo que no es un número, int() produce un ValueError y el programa se detiene con un error:

How many pages do you need? five
ValueError: invalid literal for int() with base 10: 'five'

Para números enteros, puedes revisar primero con el método de cadenas .isdigit(), que devuelve True solo si todos los caracteres son dígitos:

pages = input("How many pages do you need? ").strip()

if pages.isdigit():
    pages = int(pages)
    print(f"A {pages}-page website. Great!")
else:
    print("Please enter a whole number, like 5.")

.isdigit() no acepta decimales ni números negativos. Para esos casos hay una herramienta más general, try y except, que verás más adelante en esta publicación. Pero primero necesitamos una forma de volver a preguntar cuando la respuesta es incorrecta. Para eso sirven los ciclos while.

Ciclos While

Un ciclo while repite un bloque de código mientras su condición sea verdadera. Se parece mucho a una sentencia if: una palabra clave, una condición, dos puntos y un bloque con sangría:

count = 1

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

Esto imprime los números del 1 al 5. Esto es lo que pasa paso a paso:

  1. Python revisa la condición count <= 5. Es True (1 es menor o igual que 5), así que ejecuta el bloque: imprime 1 y luego le suma 1 a count.
  2. Python regresa al inicio y vuelve a revisar la condición. count ahora vale 2, sigue siendo True, así que ejecuta el bloque otra vez.
  3. Esto se repite hasta que count llega a 6. Ahora la condición es False, así que Python se salta el bloque y continúa con lo que venga después del ciclo.

La diferencia con if: una sentencia if ejecuta su bloque una vez como máximo. Un ciclo while sigue regresando a revisar la condición.

While vs. For

La Parte 1 también presentó los ciclos for. Ambos repiten código, pero sirven para trabajos distintos:

  • Usa un ciclo for cuando sabes qué vas a recorrer: cada elemento de una lista, cada clave de un diccionario o un número fijo de veces con range().
  • Usa un ciclo while cuando no sabes de antemano cuántas veces vas a repetir; solo conoces la condición para detenerte. “Sigue preguntando hasta que la respuesta sea válida.” “Sigue funcionando hasta que el usuario salga.” “Sigue hasta que la lista esté vacía.”

Evitar Ciclos Infinitos

Si la condición de un ciclo while nunca se vuelve False, el ciclo se ejecuta para siempre. A esto se le llama ciclo infinito, y todo programador escribe uno tarde o temprano. La causa más común es olvidar actualizar la variable de la condición:

count = 1

while count <= 5:
    print(count)
    # se olvidó count += 1, así que count siempre vale 1 y esto nunca termina

Si tu programa se queda atrapado en un ciclo infinito, presiona Ctrl + C en la terminal para detenerlo. Luego revisa que algo dentro del ciclo haga que la condición termine siendo False.

Dejar que el Usuario Decida Cuándo Parar

Este ciclo repite lo que escribe el usuario hasta que escribe quit. El valor "quit" se llama centinela: un valor especial que indica el final:

message = ""

while message != "quit":
    message = input("Type something (or 'quit' to stop): ").strip().lower()
    if message != "quit":
        print(f"You said: {message}")

Observa que message empieza como una cadena vacía, así que la condición es True la primera vez y el ciclo puede empezar. Observa también el if dentro del ciclo: sin él, el programa repetiría quit antes de detenerse.

Usar una Bandera

Cuando un ciclo puede terminar por varias razones distintas, suele ser más claro usar una sola variable bandera (flag) que indique si el programa debe seguir funcionando:

active = True

while active:
    command = input("Enter a command (help, status, quit): ").strip().lower()

    if command == "quit":
        active = False
    elif command == "help":
        print("Available commands: help, status, quit")
    elif command == "status":
        print("All systems running.")
    else:
        print(f"Unknown command: {command}")

Cualquier parte del ciclo puede poner active = False para terminarlo. La línea del while queda corta y fácil de leer.

Break y Continue

Dos palabras clave te dan más control dentro de un ciclo.

Salir de un Ciclo con break

break sale del ciclo de inmediato, saltándose el código que quede en el bloque e ignorando la condición. Un patrón muy común es while True (un ciclo que se ejecutaría para siempre) con un break que lo termina cuando ya acabaste:

while True:
    city = input("Enter a city you'd like to visit (or 'quit'): ").strip()

    if city.lower() == "quit":
        break

    print(f"I'd love to go to {city.title()}!")

print("Thanks for playing.")

while True se lee de forma natural: “sigue haciendo esto hasta que algo te diga que pares”. Además, evita tener que preparar un valor inicial solo para que la condición se cumpla la primera vez.

Saltar con continue

continue se salta el resto de la vuelta actual del ciclo y regresa directamente a la condición. Este ciclo imprime solo los números impares del 1 al 10:

number = 0

while number < 10:
    number += 1
    if number % 2 == 0:
        continue      # número par: se salta el print de abajo
    print(number)

Observa que number += 1 va antes del continue. Si fuera después, un número par se saltaría la actualización y el ciclo se quedaría atorado en él para siempre.

Preguntar Hasta que la Respuesta Sea Válida

Ahora puedes resolver el problema de antes: cuando el usuario escribe algo inválido, vuelve a preguntar en lugar de detenerte con un error.

while True:
    pages = input("How many pages do you need? ").strip()

    if pages.isdigit() and int(pages) > 0:
        pages = int(pages)
        break

    print("Please enter a whole number greater than 0.")

print(f"Got it: {pages} pages.")

Una sesión podría verse así:

How many pages do you need? five
Please enter a whole number greater than 0.
How many pages do you need? 0
Please enter a whole number greater than 0.
How many pages do you need? 6
Got it: 6 pages.

Aceptar Cualquier Número con try y except

.isdigit() solo funciona con números enteros positivos. Para aceptar precios como 19.99 o números negativos, usa try y except. Python intenta ejecutar el código del bloque try; si ocurre un ValueError, ejecuta el bloque except en lugar de detenerse con un error:

while True:
    answer = input("What's your monthly budget? $").strip()
    try:
        budget = float(answer)
        break
    except ValueError:
        print("Please enter a number, like 1500 or 1499.99.")

print(f"Budget: ${budget:,.2f}")

Si float(answer) funciona, se ejecuta el break y el ciclo termina. Si falla, Python salta al except, imprime el mensaje y el ciclo vuelve a preguntar. Aprenderás mucho más sobre el manejo de errores en la Parte 8: Archivos y Excepciones; por ahora, este patrón es todo lo que necesitas para leer números de forma segura.

Ciclos While con Listas y Diccionarios

Los ciclos while combinan de forma natural con las listas y los diccionarios de la Parte 3.

Mover Elementos Entre Listas

Un ciclo while puede seguir trabajando hasta que una lista quede vacía. Recuerda que una lista vacía cuenta como falsa, así que while unreviewed: significa “mientras todavía queden elementos”:

unreviewed = ["Home", "About", "Services", "Contact"]
approved = []

while unreviewed:
    page = unreviewed.pop(0)       # toma la primera página de la lista
    print(f"Reviewing {page}...")
    approved.append(page)

print(f"Approved pages: {approved}")
print(f"Left to review: {unreviewed}")
Reviewing Home...
Reviewing About...
Reviewing Services...
Reviewing Contact...
Approved pages: ['Home', 'About', 'Services', 'Contact']
Left to review: []

Quitar Todas las Copias de un Valor

En la Parte 3 viste que quitar elementos de una lista mientras la recorres con for hace que se salten elementos. .remove() solo borra la primera coincidencia, pero un ciclo while puede seguir llamándolo hasta que no quede ninguna copia:

tags = ["old", "web", "old", "seo", "old"]

while "old" in tags:
    tags.remove("old")

print(tags)   # ['web', 'seo']

Llenar un Diccionario con Datos del Usuario

Este ciclo reúne las respuestas de varias personas en un diccionario hasta que ya no queda nadie a quien preguntar:

responses = {}

while True:
    name = input("What's your name? ").strip()
    color = input("What's your favorite brand color? ").strip()
    responses[name] = color

    again = input("Is there someone else? (yes/no) ").strip().lower()
    if again != "yes":
        break

print("--- Results ---")
for name, color in responses.items():
    print(f"{name} likes {color}.")

Todo Junto: Una Herramienta para Recibir Proyectos

Este es un pequeño programa de línea de comandos que reúne los detalles de un nuevo proyecto web. Usa todo lo de esta publicación, más las listas, los diccionarios y las sentencias if de las partes anteriores:

HOURLY_RATE = 85
HOURS_PER_PAGE = 4

print("Welcome! Let's plan your new website.")

# Texto obligatorio: pregunta hasta que no esté vacío
while True:
    business = input("Business name: ").strip()
    if business:
        break
    print("The business name can't be empty.")

# Una lista de páginas, que se llena hasta que el usuario escribe 'done'
pages = []
print("Enter the pages you need, one at a time. Type 'done' when finished.")
while True:
    page = input("Page name: ").strip().title()
    if page.lower() == "done":
        if pages:
            break
        print("Please add at least one page.")
        continue
    if page in pages:
        print(f"{page} is already on the list.")
        continue
    if page:
        pages.append(page)

# Una pregunta de sí o no que solo acepta yes o no
while True:
    rush = input("Do you need it within 2 weeks? (yes/no) ").strip().lower()
    if rush in ("yes", "no"):
        break
    print("Please answer yes or no.")

# Calcular y mostrar la cotización
hours = len(pages) * HOURS_PER_PAGE
total = hours * HOURLY_RATE
if rush == "yes":
    total = total * 1.25

print(f"\nQuote for {business}")
for number, page in enumerate(pages, start=1):
    print(f"  {number}. {page}")
print(f"Estimated hours: {hours}")
print(f"Rush delivery: {'Yes' if rush == 'yes' else 'No'}")
print(f"Total: ${total:,.2f}")

Esta es una sesión de ejemplo, con algunos errores para mostrar cómo funciona la validación:

Welcome! Let's plan your new website.
Business name: 
The business name can't be empty.
Business name: Bright Bakery
Enter the pages you need, one at a time. Type 'done' when finished.
Page name: done
Please add at least one page.
Page name: home
Page name: menu
Page name: Home
Home is already on the list.
Page name: contact
Page name: done
Do you need it within 2 weeks? (yes/no) maybe
Please answer yes or no.
Do you need it within 2 weeks? (yes/no) no

Quote for Bright Bakery
  1. Home
  2. Menu
  3. Contact
Estimated hours: 12
Rush delivery: No
Total: $1,020.00

Ejecútalo tú mismo e intenta romperlo: deja campos vacíos, escribe la misma página dos veces o responde “maybe”. Luego intenta ampliarlo: pide un presupuesto con try/except, o avisa al usuario si su presupuesto es menor que la cotización.

Errores Comunes de Principiantes

Olvidar actualizar la variable del ciclo. Si nada dentro del ciclo cambia la condición, el ciclo nunca termina. Asegúrate de que cada camino dentro del ciclo avance hacia el final, y recuerda Ctrl + C para detener un programa descontrolado.

Comparar la entrada con un número. input() devuelve texto, así que if answer == 5: nunca es verdadero: "5" y 5 no son iguales. Convierte primero con int(), o compara con la cadena "5".

No limpiar la entrada. if answer == "yes": falla cuando el usuario escribe "Yes" o " yes". Usa .strip().lower() en las respuestas que vayas a comparar.

Poner continue antes de la actualización. Si continue se ejecuta antes de la línea que cambia la variable del ciclo, el ciclo se atora. Actualiza la variable primero.

Usar while donde for es más sencillo. Para recorrer cada elemento de una lista o repetir algo un número fijo de veces, un ciclo for es más corto y no puede quedarse funcionando para siempre por accidente:

# Funciona, pero es más código y es fácil equivocarse
i = 0
while i < len(pages):
    print(pages[i])
    i += 1

# Más sencillo
for page in pages:
    print(page)

Usar break fuera de un ciclo. break y continue solo funcionan dentro de un ciclo. Usarlos en cualquier otro lugar es un SyntaxError.

Convertir sin revisar. int(input(...)) falla con cualquier cosa que no sea un número entero. Cuando la entrada viene de una persona, valídala en un ciclo con .isdigit() o con try/except.

Ejercicios de Práctica

  1. Pide al usuario su nombre y su lenguaje de programación favorito, e imprime una oración que use ambos.
  2. Escribe una cuenta regresiva que pida un número inicial y cuente hacia atrás hasta 1 con un ciclo while, y al final imprima Liftoff!.
  3. Sigue pidiendo números al usuario hasta que escriba done, y luego imprime cuántos números escribió, el total y el promedio.
  4. Escribe un juego de adivinar el número: elige un número secreto, sigue pidiendo intentos, di “muy alto” o “muy bajo” después de cada uno y felicita al usuario cuando acierte. Cuenta cuántos intentos le tomó.
  5. Pide una contraseña hasta que tenga al menos 8 caracteres y al menos un dígito. (Pista: any(c.isdigit() for c in password).)
  6. Crea un programa sencillo de lista de pendientes que acepte los comandos add, list, remove y quit.

El ejercicio 4 es un clásico. Puedes comparar tu versión con la de 100 Días de Python: Día 005 Adivina el Número.

Conclusión

input() y los ciclos while convierten tus scripts en programas con los que la gente puede interactuar. input() reúne información, siempre como texto, así que recuerda limpiarla con .strip() y .lower() y convertirla con int() o float(). Los ciclos while repiten código mientras una condición sea verdadera, lo que los hace perfectos para preguntar hasta obtener una respuesta válida, seguir funcionando hasta que el usuario salga o trabajar con una lista hasta vaciarla.

Usa break para salir de un ciclo en cuanto termines, continue para saltar adelante y una bandera cuando un ciclo puede terminar de varias formas. Sobre todo, asegúrate de que cada ciclo tenga una salida.

Siguiente en la serie Fundamentos de Python: Funciones, cómo agrupar tu código en piezas reutilizables.

Serie Fundamentos de Python: Parte 1: Lo que Todo Principiante Debería Saber · Parte 2: Variables y Tipos de Datos · Parte 3: Listas y Diccionarios · Parte 4: La Sentencia If · Parte 5: Entrada del Usuario y Ciclos While · Parte 6: Funciones · Parte 7: Clases · Parte 8: Archivos y Excepciones · Parte 9: Cómo Probar tu Código