El Día 004 del reto 100 Días de Python crea contraseñas a partir de cantidades de letras, símbolos y números elegidas por el usuario. Es un gran siguiente paso después de la generación de números aleatorios del Día 003, esta vez combinando random.choice() con ciclos for e indexación de listas para construir algo carácter por carácter.
Esta guía recorre el código fuente completo del Día 004, explica cómo se arma la contraseña y, algo importante, sigue paso a paso lo que realmente hacen los ciclos, ya que el comportamiento real aquí es un poco distinto de lo que sugieren las cantidades de caracteres.
Descripción del Proyecto
El programa mantiene tres listas de caracteres: letras mayúsculas y minúsculas, símbolos y dígitos. Pregunta cuántos caracteres de cada tipo quiere el usuario, construye una lista inicial de letras aleatorias y luego sobrescribe partes de esa lista con símbolos y números aleatorios antes de mezclar el resultado.
Código Fuente
El proyecto del Día 004 está en day004/main.py, dentro del repositorio 100daysofpython:
import random
def main():
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
symbols = ['!', '@', '#', '$', '%', '^', '&', '*', '+']
numbers = ['0','1','2','3','4','5','6','7','8','9']
print("Welcome to the Python Password Generator!")
pwd_letters = int(input("How many characters would you like in your password? "))
pwd_symbols = int(input("How many symbols would you like? "))
pwd_numbers = int(input("How many numbers would you like? "))
password_chars = []
# pick random letters
for char in range(pwd_letters):
password_chars.append(random.choice(letters))
# pick random symbols
for symbol in range(pwd_symbols):
password_chars[symbol] = random.choice(symbols)
# pick random numbers
for number in range(pwd_numbers):
password_chars[pwd_symbols + number] = random.choice(numbers)
# shuffle so it's not predictable like letters→symbols→numbers
random.shuffle(password_chars)
password = "".join(password_chars)
print(f"Your password is: {password}")
if __name__ == "__main__":
main()
Cómo Funciona el Programa
Construir la Lista Inicial
for char in range(pwd_letters):
password_chars.append(random.choice(letters))
Este ciclo se ejecuta pwd_letters veces; en cada una usa random.choice(letters) para elegir una letra al azar y la agrega con .append() a password_chars. Después de este ciclo, la longitud de la lista es igual a pwd_letters.
Sobrescribir Posiciones, No Agregar
for symbol in range(pwd_symbols):
password_chars[symbol] = random.choice(symbols)
for number in range(pwd_numbers):
password_chars[pwd_symbols + number] = random.choice(numbers)
Esta es la parte que vale la pena leer con cuidado. Estos ciclos usan password_chars[symbol] = ..., no .append(), lo que significa que sobrescriben posiciones existentes de la lista en lugar de agregar caracteres nuevos. El ciclo de símbolos reemplaza los índices del 0 al pwd_symbols - 1, y el ciclo de números reemplaza las siguientes pwd_numbers posiciones.
Mezclar y Unir
random.shuffle(password_chars)
password = "".join(password_chars)
random.shuffle() reordena la lista en el mismo lugar, de modo que la contraseña final no siga un patrón predecible de letras, luego símbolos y luego números. "".join(password_chars) combina después todos los caracteres de la lista en una sola cadena.
Seguimiento del Comportamiento Real
Como los ciclos de símbolos y números sobrescriben la lista en lugar de ampliarla, la longitud final de la contraseña siempre es igual a pwd_letters, no a la suma de las tres entradas, aunque el programa pregunte por cada una por separado.
Recorramos un ejemplo: si un usuario ingresa 8 para las letras, 2 para los símbolos y 2 para los números, esto es lo que ocurre:
- La lista comienza con 8 letras aleatorias en los índices del
0al7. - El ciclo de símbolos sobrescribe los índices
0y1con símbolos aleatorios. - El ciclo de números sobrescribe los índices
2y3con números aleatorios. - Los índices del
4al7siguen siendo las letras aleatorias originales. - La contraseña final mide 8 caracteres (2 símbolos, 2 números y 4 letras), no 12 caracteres como podrían sugerir las tres preguntas por separado.
Se vuelve más serio si pwd_symbols + pwd_numbers es mayor que pwd_letters. En ese caso, el ciclo de números intenta asignar a un índice que todavía no existe, y Python lanza un IndexError: list assignment index is out of range, lo que hace fallar el programa.
Qué Enseña Este Proyecto
El Día 004 practica:
- Trabajar con el módulo
random, en concretorandom.choice()yrandom.shuffle() - Construir y modificar una lista con un ciclo
for - La diferencia entre
.append()(agregar un elemento nuevo) y la asignación por índice (sobrescribir un elemento existente) - Unir una lista de caracteres en una sola cadena con
"".join()
También introduce una idea práctica de seguridad: la variedad y un orden impredecible hacen que las contraseñas generadas sean más difíciles de adivinar. Para generar contraseñas en producción, el módulo secrets de Python sería preferible a random, ya que está diseñado específicamente para aleatoriedad sensible a la seguridad; este proyecto del reto se enfoca en aprender los fundamentos de Python, no en construir una herramienta de seguridad lista para producción.
Ejecutar el Proyecto
git clone https://github.com/victorhugo81/100daysofpython.git
cd 100daysofpython/day004
python main.py
Posibles Siguientes Pasos
Cuando entiendas el comportamiento existente, intenta corregirlo y ampliarlo:
- Cambia los ciclos de símbolos y números para que usen
.append()en lugar de la asignación por índice, de modo que la longitud final de la contraseña sí sea igual a la suma de las tres entradas - Agrega validación para que el programa muestre un mensaje de error claro en lugar de fallar cuando
symbols + numberssupere aletters - Cambia
randompor el módulosecretspara que el generador sea seguro en el mundo real - Permite que el usuario establezca una longitud total mínima para la contraseña sin importar cómo se reparta entre los tipos de caracteres
Conclusión
El Día 004 del reto 100 Días de Python combina ciclos, modificación de listas y el módulo random para construir un generador de contraseñas, y su enfoque de sobrescribir para combinar letras, símbolos y números es un recordatorio útil de que un programa puede ejecutarse sin errores y aun así no hacer exactamente lo que sus preguntas dan a entender. Recorrer el código línea por línea, como lo acaba de hacer esta guía, es uno de los hábitos de depuración más valiosos que puedes desarrollar como principiante.
Consulta el código fuente del Día 004 en GitHub y sigue explorando el índice de proyectos del repositorio mientras construyes más programas en Python, un día y un proyecto pequeño a la vez.
