2.11. Condicionales

Un condicional ejecuta un bloque de código solo cuando alguna prueba se evalúa como verdadera. La palabra clave es if, seguida opcionalmente de una o más ramas elif («else if») y una else final.

n = 42

if n > 0:
    print("positive")
elif n < 0:
    print("negative")
else:
    print("zero")

El cuerpo de cada rama es todo lo que está indentado bajo ella (cuatro espacios por convención). Python recorre las ramas en orden, ejecuta la primera cuya prueba sea verdadera y omite el resto. El bloque else se ejecuta solo si todas las pruebas anteriores fueron falsas; siempre es opcional.

Un diagrama de flujo que muestra if/elif/else: dos pruebas de decisión en rombo con sus cuerpos, que caen hasta un cuerpo else final cuando ambas pruebas son falsas.

Solo se ejecuta una rama. Las pruebas se evalúan de arriba abajo hasta que una tiene éxito; el resto se omiten.

2.11.1. Veracidad

Una prueba en un if no tiene que devolver True o False – cualquier valor cuenta como verdadero (truthy) o falso (falsy). Los valores falsos son:

  • False y None

  • El número cero: 0, 0.0

  • Secuencias y colecciones vacías: "", [], (), {}, b""

Todo lo demás es verdadero. Esto te permite escribir pruebas compactas:

if name:                     # false on empty string
    print("hello", name)

if items:                    # false on empty list, dict, etc.
    process(items)

Ten en cuenta que la veracidad cambia el significado. if value: no es lo mismo que if value is not None: – el primero también es falso cuando value es 0 o "". Cuando realmente quieres decir «¿es esto exactamente None?», usa is None / is not None explícitamente.

2.11.2. Expresiones ternarias

Un condicional puede aparecer dentro de una expresión:

label = "even" if n % 2 == 0 else "odd"

Se lee como «label es "even" si n % 2 == 0 de lo contrario "odd".» Útil para líneas únicas; para cualquier cosa de más de una línea, una sentencia if completa es más fácil de leer.

2.11.3. Anidamiento y retornos tempranos

Los condicionales pueden anidarse arbitrariamente profundo, pero cada capa adicional de indentación hace que una función sea más difícil de leer. El ejemplo siguiente comprueba cuatro condiciones antes de hacer el trabajo real y deja la línea útil enterrada cuatro niveles de indentación adentro:

def process(item):
    if item is not None:
        if item.is_valid():
            if item.size() > 0:
                if item.owner == "me":
                    return do_the_work(item)
    return None

Dos patrones aplanan este tipo de código.

2.11.3.1. Retornos tempranos para guardas

Maneja primero cada caso de «abandono», cada uno con su propio return, de modo que la lógica principal se quede en la indentación exterior. Cada guarda se lee como «este no es un caso que manejemos; salir»:

def process(item):
    if item is None:
        return None
    if not item.is_valid():
        return None
    if item.size() == 0:
        return None
    if item.owner != "me":
        return None
    return do_the_work(item)

El «camino principal» es ahora una sola línea al final de la función, no enterrada dentro de cuatro capas. Este estilo se llama a veces el patrón de cláusula de guarda.

2.11.3.2. Combinar pruebas con and / or

Cuando varias condiciones deben cumplirse todas para la misma rama, combínalas con and en lugar de anidar. Las condiciones que activan la rama cada una de forma independiente se combinan con or:

# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
    save()

# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
    whitespace_count += 1

Ambas formas hacen cortocircuito, así que una comprobación costosa en el lado derecho solo se ejecuta cuando las comprobaciones más baratas de la izquierda no han resuelto ya la cuestión.