Nivel: Principiante
Tema: Strings, diccionarios, bucles, validación de entradas, tests con pytest
Objetivo: Contar cuántas veces aparece cada carácter en una cadena, devolviendo un diccionario con las frecuencias.

Enunciado
Crea una función llamada frecuencia_caracteres(texto) que:
- Reciba un valor
texto. - Si
textoesNone, devuelva un diccionario vacío{}. - Si
textono es unstr, lanceTypeError. - Devuelva un diccionario donde:
- las claves sean los caracteres del texto,
- los valores sean el número de veces que aparece cada carácter.
- Debe contar todos los caracteres, incluidos espacios y símbolos.
Ejemplos
frecuencia_caracteres("hola")→{"h": 1, "o": 1, "l": 1, "a": 1}frecuencia_caracteres("hola hola")→{"h": 2, "o": 2, "l": 2, "a": 2, " ": 1}frecuencia_caracteres("")→{}frecuencia_caracteres(None)→{}frecuencia_caracteres(123)→ TypeError
Pistas
- Usa un diccionario vacío para acumular los conteos.
- Recorre la cadena carácter por carácter.
- Si el carácter ya existe como clave, incrementa su valor.
- Si no existe, inicialízalo en
1.
Solución explicada (paso a paso)
- Si el texto es
None, no hay caracteres que contar → devolvemos{}. - Si la entrada no es una cadena, lanzamos
TypeError. - Creamos un diccionario vacío
frecuencias. - Recorremos cada carácter del texto:
- si ya está en el diccionario, sumamos 1,
- si no, lo añadimos con valor 1.
- Devolvemos el diccionario final.
Python
def frecuencia_caracteres(texto: str | None) -> dict: """ Cuenta la frecuencia de cada carácter en una cadena. Reglas: - None -> {} - No str -> TypeError - str -> diccionario {caracter: frecuencia} """ if texto is None: return {} if not isinstance(texto, str): raise TypeError("El parámetro 'texto' debe ser una cadena (str) o None.") frecuencias = {} for caracter in texto: if caracter in frecuencias: frecuencias[caracter] += 1 else: frecuencias[caracter] = 1 return frecuencias
Python
import pytestfrom reto_04_frecuencia_caracteres import frecuencia_caracteresdef test_texto_normal(): assert frecuencia_caracteres("hola") == { "h": 1, "o": 1, "l": 1, "a": 1, }def test_texto_con_espacios(): assert frecuencia_caracteres("hola hola")[" "] == 1def test_cadena_vacia(): assert frecuencia_caracteres("") == {}def test_none_devuelve_diccionario_vacio(): assert frecuencia_caracteres(None) == {}def test_tipo_incorrecto_lanza_typeerror(): with pytest.raises(TypeError): frecuencia_caracteres(123)
Ejecuta:
pytest -q
Variantes para subir de nivel (opcional)
- Ignorar espacios: no contar
" " - Normalizar mayúsculas/minúsculas:
"H"y"h"cuentan como el mismo carácter - Usar
collections.Counter: compara claridad y concisión - Frecuencia de palabras en lugar de caracteres
Lo que aprendiste
- Cómo usar diccionarios como contadores
- Cómo recorrer strings de forma eficiente
- Cómo definir reglas claras para casos borde
- Cómo testear estructuras de datos con
pytest
Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.
Sigue con Reto #5 — Filtrar números pares de una lista para practicar listas, condicionales y lógica simple aplicada.