any() y all() en Python: evaluar condiciones sobre iterables de forma eficiente

any() y all() comprueban condiciones sobre iterables de forma eficiente usando short-circuit evaluation: se detienen en cuanto conocen el resultado, sin procesar el resto de los elementos.

Funcionamiento básico

# any(): True si al menos UN elemento es truthy
print(any([False, False, True, False]))  # True
print(any([0, "", None, False]))         # False
print(any([]))                           # False (vacío)

# all(): True si TODOS los elementos son truthy
print(all([True, True, True]))           # True
print(all([True, False, True]))          # False
print(all([]))                           # True (vacío — vacuously true)

# Con listas de números
numeros = [2, 4, 6, 8, 10]
print(all(x % 2 == 0 for x in numeros))  # True — todos pares
print(any(x > 5 for x in numeros))       # True — alguno > 5

Short-circuit evaluation

Ambas funciones se detienen en cuanto pueden determinar el resultado final, lo que las hace eficientes con generadores grandes:

def comprobar(x):
    print(f"  comprobando {x}")
    return x > 0

datos = [1, 2, -3, 4, 5]

print("any() con negativos:")
resultado = any(comprobar(x) for x in datos)
# comprobando 1 ? True ? se detiene aquí
print(f"Resultado: {resultado}n")

datos_negativos = [-1, -2, -3]
print("all() con negativos:")
resultado = all(comprobar(x) for x in datos_negativos)
# comprobando -1 ? False ? se detiene aquí
print(f"Resultado: {resultado}")

Validación de formularios

def validar_formulario(datos):
    campos_requeridos = ["nombre", "email", "edad"]

    # Comprobar que todos los campos existen y tienen valor
    if not all(datos.get(campo) for campo in campos_requeridos):
        return False, "Faltan campos obligatorios"

    # Comprobar tipos
    if not isinstance(datos.get("edad"), int):
        return False, "La edad debe ser un número entero"

    if not 0 < datos["edad"] < 150:
        return False, "Edad fuera de rango"

    return True, "OK"

datos1 = {"nombre": "Ana", "email": "[email protected]", "edad": 28}
datos2 = {"nombre": "Luis", "email": "", "edad": 34}  # email vacío

print(validar_formulario(datos1))  # (True, 'OK')
print(validar_formulario(datos2))  # (False, 'Faltan campos obligatorios')

Comprobación de permisos

permisos_usuario = {"leer", "escribir"}
permisos_admin   = {"leer", "escribir", "ejecutar", "borrar"}

def puede_acceder(usuario_permisos, recurso_requerido):
    """True si el usuario tiene TODOS los permisos requeridos."""
    return all(p in usuario_permisos for p in recurso_requerido)

def tiene_algun_permiso(usuario_permisos, permisos_posibles):
    """True si el usuario tiene AL MENOS UNO de los permisos."""
    return any(p in usuario_permisos for p in permisos_posibles)

operacion_requerida = ["leer", "ejecutar"]

print(puede_acceder(permisos_usuario, operacion_requerida))  # False
print(puede_acceder(permisos_admin, operacion_requerida))    # True

print(tiene_algun_permiso(permisos_usuario, ["ejecutar", "borrar"]))  # False
print(tiene_algun_permiso(permisos_admin, ["ejecutar", "borrar"]))    # True

Procesado de datos

usuarios = [
    {"nombre": "Ana",   "verificado": True,  "activo": True},
    {"nombre": "Luis",  "verificado": False, "activo": True},
    {"nombre": "María", "verificado": True,  "activo": False},
]

# ¿Todos verificados?
todos_verificados = all(u["verificado"] for u in usuarios)
print(todos_verificados)  # False

# ¿Alguno inactivo?
alguno_inactivo = any(not u["activo"] for u in usuarios)
print(alguno_inactivo)   # True

# Filtrar los que cumplen múltiples condiciones
validos = [u for u in usuarios if u["verificado"] and u["activo"]]
print([u["nombre"] for u in validos])  # ['Ana']

any() vs all() con generadores vs listas

# BIEN: generador — short-circuit real
if any(es_primo(n) for n in rango_grande):
    print("Hay al menos un primo")

# MAL: lista — evalúa TODO antes de any()
if any([es_primo(n) for n in rango_grande]):
    print("Hay al menos un primo")

Usa siempre una expresión generadora (sin corchetes) cuando pases a any() o all(). De esta forma el short-circuit funciona de verdad y no evalúas el iterable completo antes de comprobar la condición.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP