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.
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:
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.