Clase 02 · 30 minGratis
Cifrado César: de script a función
Clase 2 del curso gratis de buenas prácticas en Python: implementamos el cifrado César, vemos por qué Pylint castiga los nombres de una letra y pasamos de programación estructural a funcional.
Toca cualquier marca ▸ 0:00 de los apuntes y el video salta a ese momento. Abrir en YouTube
Qué es un cifrado César
Cada letra se reemplaza por la que está clave posiciones más adelante en el
alfabeto. Con clave 1, la A pasa a B y la B a C; mamá queda como NBNB.
Cuando se llega al final, se da la vuelta: con clave 1, la Z vuelve a ser A.
Como trabajamos en español, nuestro alfabeto incluye la Ñ: 27 letras. Muchas implementaciones de internet la ignoran, y eso cambia los resultados.
Nombres de una letra: el error a propósito
La primera versión se escribe mal adrede, con variables X, Y y Z. Pylint
la califica con 0/10 , y con razón:
- Las constantes van en MAYÚSCULAS (
ALFABETO,MENSAJE). - Un nombre de una letra no le dice nada a tu yo del futuro.
- Las variables van en snake_case (
texto_cifrado), no en camelCase (textoCifrado, más típico de Java) .
El Zen de Python lo resume: explícito es mejor que implícito .
El algoritmo
Recorremos el texto letra por letra, buscamos su posición en el alfabeto, le sumamos la clave y tomamos la letra de la nueva posición. Lo que no es letra (espacios, signos, números) pasa tal cual.
El truco para dar la vuelta al alfabeto es el módulo %
: 27 % 27 es 0 y 28 % 27 es 1, así que el resultado nunca
se sale de las 27 posiciones.
Repetir código es la señal
Para descifrar, la primera tentación es copiar el bloque y cambiarle el signo. Eso funciona, pero es programación estructural: todo en un archivo, todo seguido . Hay otros paradigmas (reactivo, orientado a objetos); aquí usamos el funcional: si algo se repite, debe ser una función .
"""
Modulo para hacer cifrado cesar
"""
def cifrado_cesar(texto, clave):
"""función que implementa algoritmo de cifrado cesar
Args:
texto (str): texto a ser procesado/cifrado
clave (int): clave de cifrado
Returns:
str: texto procesado/cifrado
"""
alfabeto = "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
texto_cifrado = ""
for letra in texto.upper():
if letra in alfabeto:
posicion = alfabeto.index(letra)
nueva_posicion = (posicion + clave) % len(alfabeto)
texto_cifrado += alfabeto[nueva_posicion]
else:
texto_cifrado += letra
return texto_cifradoY aparece la ventaja: descifrar es la misma función con la clave negativa
. cifrado_cesar("IPMB", -1) devuelve HOLA.
Con el docstring de la función, Pylint vuelve a 10/10 . Al empezar la clase 3, la función se muda a su propio archivo.
El reto de esta clase
Escribe una función descifrado_cesar(texto, clave) que no duplique
lógica, y comprueba a mano que descifrado_cesar(cifrado_cesar("hola mundo", 7), 7)
devuelve HOLA MUNDO.
Ver una solución posibleOcultar la solución
from funciones.cifrado_cesar import cifrado_cesar
def descifrado_cesar(texto, clave):
"""Deshace el cifrado César aplicando la misma función con la clave negativa."""
return cifrado_cesar(texto, -clave)
print(descifrado_cesar(cifrado_cesar("hola mundo", 7), 7)) # HOLA MUNDO