Apuntes sobre Python

La indentación no es estilo: es sintaxis.

Formato de cadenas e input()

En la lección anterior viste cómo construir mensajes uniendo cadenas con +:

>>> nombre = "cristina"
>>> edad = 25
>>> mensaje = "hola " + nombre + ", tienes " + str(edad) + " años"
>>> print(mensaje)
hola cristina, tienes 25 años

Funciona, pero tiene tres problemas evidentes: los + ensucian la lectura, hay que recordar añadir espacios manualmente, y hay que convertir los números a string con str() para no provocar un TypeError. Python ofrece una sintaxis mucho más limpia para esto: las f-strings.

Sintaxis básica de las f-strings

Una f-string es una cadena prefijada con la letra f. Dentro de ella, todo lo que pongas entre llaves { } se sustituye por el valor de esa expresión:

>>> nombre = "cristina"
>>> edad = 25
>>> print(f"hola {nombre}, tienes {edad} años")
hola cristina, tienes 25 años

Se leen casi como leerías la frase final. No hace falta concatenar, ni convertir los números, ni preocuparse por los espacios: todo lo que está fuera de las llaves se imprime tal cual.

Nota: la f tiene que estar pegada a las comillas, sin espacio. Si te olvidas de la f, las llaves se imprimirán literalmente como parte del texto. Es uno de los errores más fáciles de cometer.

>>> print("hola {nombre}")    # sin la f, las llaves son literales
hola {nombre}

Expresiones dentro de las llaves

Dentro de las llaves no estás limitado a poner nombres de variables. Puedes escribir cualquier expresión de Python: operaciones, llamadas a métodos, llamadas a funciones, comparaciones, accesos a listas o diccionarios... Python evalúa la expresión y mete el resultado:

>>> nombre = "cristina"
>>> precio = 12.5
>>> cantidad = 3

>>> print(f"hola {nombre.title()}")
hola Cristina
>>> print(f"total: {precio * cantidad}")
total: 37.5
>>> print(f"la cadena tiene {len(nombre)} letras")
la cadena tiene 8 letras
>>> print(f"¿es adulto? {edad >= 18}")
¿es adulto? True

Esta capacidad es la que convierte a las f-strings en una herramienta de propósito general: sustituyen tanto a la concatenación con + como al uso de print() con varios argumentos separados por comas.

Especificadores de formato

Dentro de las llaves puedes añadir, después de dos puntos, indicaciones sobre cómo quieres que se muestre el valor. La sintaxis general es {valor:especificador}.

Decimales

Para números con coma flotante, lo más habitual es controlar cuántos decimales mostrar. :.2f redondea a dos decimales:

>>> precio = 7.5
>>> iva = 0.21
>>> total = precio * (1 + iva)
>>> print(f"total: {total}")
total: 9.075
>>> print(f"total: {total:.2f} €")
total: 9.08 €

El número antes de la f es la cantidad de decimales. :.0f muestra el número como entero (redondeando), :.4f mostraría cuatro decimales.

Anchura y alineación

Si quieres alinear texto en columnas, indica una anchura mínima. Por defecto los números se alinean a la derecha y el texto a la izquierda, pero puedes forzarlo con < (izquierda), > (derecha) o ^ (centro):

>>> for fruta, precio in [("manzana", 1.2), ("pera", 0.8), ("sandía", 3.5)]:
...     print(f"{fruta:<10} {precio:>6.2f} €")
manzana      1.20 €
pera         0.80 €
sandía       3.50 €

Aquí {fruta:<10} reserva diez caracteres alineados a la izquierda para el nombre, y {precio:>6.2f} reserva seis caracteres alineados a la derecha para el precio con dos decimales. El resultado es una tabla ordenada sin tener que contar espacios a mano.

Relleno con ceros

Para números con relleno de ceros a la izquierda (típico en horas, identificadores, etc.), usa 0 seguido de la anchura:

>>> for h in [7, 18, 23]:
...     print(f"{h:02d}:00")
07:00
18:00
23:00

Separador de miles

Para números grandes, una coma como especificador inserta el separador de miles (en estilo anglosajón). Si prefieres puntos al estilo español, sustitúyelos luego con .replace():

>>> poblacion = 1234567
>>> print(f"{poblacion:,}")
1,234,567
>>> print(f"{poblacion:,}".replace(",", "."))
1.234.567

Cadenas de varias líneas

Si el texto se hace largo, puedes usar triples comillas para escribirlo en varias líneas. Sigue funcionando como f-string si añades la f delante:

>>> nombre = "cristina"
>>> ciudad = "zaragoza"
>>> edad = 25
>>> ficha = f"""
... Nombre: {nombre.title()}
... Ciudad: {ciudad.title()}
... Edad:   {edad}
... """
>>> print(ficha)

Nombre: Cristina
Ciudad: Zaragoza
Edad:   25

El truco = para depurar

Si pones un signo igual al final de la expresión dentro de las llaves, Python imprime tanto el nombre como el valor. Es muy útil cuando estás depurando código y quieres ver qué tiene cada variable sin escribir su nombre dos veces:

>>> x = 7
>>> y = 12
>>> print(f"{x=}, {y=}, {x + y=}")
x=7, y=12, x + y=19

Nota: este truco existe desde Python 3.8. Es para uso de depuración: en código de producción es más limpio escribir el mensaje completo.

Comillas dentro de una f-string

Como cualquier cadena, una f-string usa unas comillas para delimitarse. Si necesitas el mismo tipo de comillas dentro, alterna comillas simples y dobles, o escápalas con barra invertida:

>>> usuario = "ignacio"
>>> print(f"hola, '{usuario}'")       # comillas simples dentro de dobles
hola, 'ignacio'
>>> print(f'hola, "{usuario}"')       # comillas dobles dentro de simples
hola, "ignacio"

Antes de las f-strings: .format() y %

Las f-strings se introdujeron en Python 3.6 (año 2016). En código más antiguo verás dos formas anteriores que cumplen la misma función:

# método .format(): sigue siendo válido
>>> print("hola {}, tienes {} años".format(nombre, edad))
hola cristina, tienes 25 años

# operador %: estilo C, muy antiguo
>>> print("hola %s, tienes %d años" % (nombre, edad))
hola cristina, tienes 25 años

Funcionan, pero son más verbosos y menos legibles. En código nuevo usa siempre f-strings; conoce las otras dos solo para saber leer código antiguo cuando te lo encuentres.

Leer datos del teclado: input()

Hasta ahora todos los datos los hemos escrito directamente en el código. Para pedirle algo al usuario por teclado, Python ofrece la función integrada input(). El programa se detiene esperando que el usuario escriba algo y pulse Enter, y devuelve lo escrito como una cadena:

>>> nombre = input("¿Cómo te llamas? ")
¿Cómo te llamas? cristina
>>> print(f"hola, {nombre}")
hola, cristina

El argumento de input() es el texto que se muestra antes de leer (el prompt). No es obligatorio, pero conviene dejar claro al usuario qué se espera de él.

Nota: input() siempre devuelve una cadena (str), incluso si el usuario escribe un número. Si necesitas tratarlo como número, tienes que convertirlo explícitamente con int() o float().

>>> edad = input("¿Cuántos años tienes? ")
¿Cuántos años tienes? 25
>>> print(edad + 1)                        # error: edad es "25" (cadena)
TypeError: can only concatenate str (not "int") to str

>>> edad = int(input("¿Cuántos años tienes? "))
¿Cuántos años tienes? 25
>>> print(edad + 1)
26

El patrón int(input(...)) o float(input(...)) es muy habitual. Tiene un riesgo: si el usuario escribe algo que no es un número, int() lanza un ValueError y el programa falla. Los métodos .isdigit() que vimos en la lección de strings, o el manejo de excepciones con try/except que verás más adelante, son las dos formas de protegerse contra eso.

Un ejemplo que combina todo

Un mini programa que aplica lo de esta lección y la anterior:

nombre = input("¿Cómo te llamas? ").strip().title()
edad = int(input("¿Cuántos años tienes? "))
altura = float(input("¿Cuánto mides en metros? "))

print(f"""
Hola, {nombre}.
Tienes {edad} años y mides {altura:.2f} m.
{"Ya eres mayor de edad." if edad >= 18 else "Aún eres menor de edad."}
""")

Fíjate en tres cosas: .strip().title() encadena dos métodos de cadena para limpiar el espacio sobrante y poner mayúscula inicial; {altura:.2f} formatea el número con dos decimales; y dentro de las llaves se puede usar incluso el operador ternario if/else que vimos en condicionales.

En la próxima lección: otros tipos de datos en Python: números enteros y decimales, booleanos, None, y la función type() para saber con qué estás trabajando.

TOP