Programar Juegos Arcade
con Python y PygameChapter 20: Formatos
Aquí debajo puedes encontrar una tabla de referencias rápidas para cuando formatees un texto. Para una explicación detallada de cómo funciona el formateo de un texto, deberás seguir leyendo.
Número | Formato | Salida | Descripción |
---|---|---|---|
3.1415926 | {:.2f} | 3.14 | 2 lugares decimales |
3.1415926 | {:+.2f} | +3.14 | 2 lugares decimales con signo |
-1 | {:+.2f} | -1.00 | 2 lugares decimales con signo |
3.1415926 | {:.0f} | 3 | Sin decimales (se redondeará) |
5 | {:0>2d} | 05 | Añade ceros por la izquierda |
1000000 | {:,} | 1,000,000 | Formato numérico con separador coma |
0.25 | {:.2%} | 25.00% | Formato porcentual |
1000000000 | {:.2e} | 1.00e+09 | Notación exponencial |
11 | {:>10d} | 11 | Alineación a la derecha |
11 | {:<10d} | 11 | Alineación a la izquierda |
11 | {:^10d} | 11 | Centrado |
20.1 Números Decimales
Intenta ejecutar el siguiente programa, imprime unos cuantos números aleatorios.
import random for i in range(10): x = random.randrange(20) print(x)
La salida está alineada por la izquierda y el aspecto de los números es horrible:
16 13 2 0 10 3 18 1 14 5
Podemos utilizar el formateo para que, alineándolos hacia la derecha, la lista de números presente un mejor aspecto. El primer paso es usar el comando format sobre la cadena. Observa:
import random for i in range(10): x = random.randrange(20) print("{}".format(x) )
Esto consigue que nuestro programa esté a un paso de alinear a la derecha el número, pero aún no hemos acabado. Observa que la cadena termina con .format(x). Realmente, todas las cadenas son instancias de la clase llamada String. Esta clase posee unos métodos que podemos invocar. Uno de ellos es el método format.
La función format no imprimirá las llaves {}, en su lugar las reemplazará con el valor contenido en x. El resultado (debajo) se parece a lo previamente ya habíamos obtenido.
7 15 4 12 3 8 7 15 12 8
Para alinear a la derecha, añadimos información extra sobre cómo se debe formatear el número contenido entre las llaves {}:
import random for i in range(10): x = random.randrange(20) print("{:2}".format(x) )
7 15 4 12 3 8 7 15 12 8
Esto está mejor; hemos alineado a la derecha los números! Pero cómo funciona? La expresión :2 que hemos añadido es todo menos intuitiva.
Vamos a desglosarlo: los símbolos { } le dicen al ordenador que vamos a formatear un número. A continuación del símbolo :, dentro de las llaves, se encuentra la información para el formato. En nuestro caso es un 2 que especifica un ancho de campo de dos caracteres. Este valor le indica al ordenador que tiene que ajustar el número dentro de un campo de dos caracteres de ancho. Por defecto, el intentaría justificar a la derecha los números y a la izquierda el texto.
Mejor aún, el programa ya no necesita llamar a str( ) para convertir el número a cadena de texto. Podemos dejar fuera las conversiones a cadena.
¿Pero qué sucede si tienes números grandes? Bien, primero creamos unos números aleatorios grandes:
import random for i in range(10): x = random.randrange(100000) print( "{:6}".format(x) )
Esto produce un resultado justificado a la derecha, pero aún no luce todo lo bien que debiera:
18394 72242 97508 21583 11508 76064 88756 77413 7930 81095
Pero, ¿dónde están las comas? Esta lista tendría un mejor aspecto poniendo separadores cada tres dígitos. Observa a continuación cómo lo hacemos :
import random for i in range(10): x = random.randrange(100000) print( "{:6,}".format(x) )
65,732 30,248 13,802 17,177 3,584 7,598 21,672 82,900 72,838 48,557
Hemos añadido una coma después del especificador de ancho de campo, con lo que ahora nuestros números tienen comas. La coma debe ir después del especificador de ancho de campo, nunca antes. Las comas son incluidas en el cálculo del ancho de campo. Por ejemplo, 1,024 tiene un ancho de campo de 5, y no de 4.
Podemos imprimir varios valores y combinarlos con texto. Ejecuta el siguiente código:
x = 5 y = 66 z = 777 print ("A - '{}' B - '{}' C - '{}'".format(x,y,z) )
El programa sustituirá las llaves por números imprimiendo, además, el texto que hay en la cadena entrecomillada:
A - '5' B - '66' C - '777'
Si existe un conjunto de tres llaves, el ordenador espera encontrar tres valores que ordenar con el comando format. El primer valor que aparezca en la lista sustituirá a la primera llave.
Algunas veces queremos que un determinado valor aparezca por duplicado, o a lo mejor, queremos que aparezca en un orden distinto al que se introduce con la función format.
x = 5 y = 66 z = 777 print ("C - '{2}' A - '{0}' B - '{1}' C y otra vez - '{2}'".format(x,y,z) )
Observa que al colocar números entre las llaves, estamos especificando el orden en que queremos que los parámetros sean imprimidos por función format. Los parámetros los enumeramos empezando por 0, de forma que x es considerado el parámetro 0.
También podemos especificar la información de formato después de los dos puntos. Por ejemplo:
x = 5 y = 66 z = 777 print ("C - '{2:4}' A - '{0:4}' B - '{1:4}' C y otra vez - '{2:4}'".format(x,y,z) )
Podemos ver que el código anterior mostrará los valores justificados hacia la derecha y con un ancho de campo de tamaño cuatro:
C - ' 777' A - ' 5' B - ' 66' C y otra vez - ' 777'
20.2 Cadenas
Veamos ahora cómo formateamos cadenas de texto.
La siguiente lista tiene un aspecto horrible.
mi_fruta = ["Manzanas", "Naranjas", "Uvas", "Peras"] mis_calorias = [4, 300, 70, 30] for i in range(4): print(mi_fruta[i], "son", mis_calorias[i], "calorías.")
Manzanas son 4 calorías. Naranjas son 300 calorías. Uvas son 70 calorías. Peras son 30 calorías.
Ahora intentémoslo usando el comando format. Observa cómo podemos introducir texto adicional y más de un valor sobre la misma línea.
mi_fruta = ["Manzanas", "Naranjas", "Uvas", "Peras"] mis_calorias = [4, 300, 70, 30] for i in range(4): print("{:7} son {:3} calorías.".format(mi_fruta[i], mis_calorias[i]) )
Manzanas son 4 calorías. Naranjas son 300 calorías. Uvas son 70 calorías. Peras son 30 calorías.
Esto luce mejor y se parece más a lo que estamos buscando. ¿Pero qué sucedería si no quisiéramos los números justificados a la derecha y el texto a la izquierda? Pues podemos usar los caracteres < y > tal como se ve a continuación:
mi_fruta = ["Manzanas", "Naranjas", "Uvas", "Peras"] mis_calorias = [4, 300, 70, 30] for i in range(4): print("{:>7} son {:<3} calorías.".format(mi_fruta[i], mis_calorias[i]) )
Manzanas son 4 calorías. Naranjas son 300 calorías. Uvas son 70 calorías. Peras son 30 calorías.
20.3 Ceros al Principio
Lo siguiente produce una salida que no está bien del todo:
for horas in range(1, 13): for minutos in range(0, 60): print( "Hora {}:{}".format(horas, minutos) )
Hora 8:56 Hora 8:57 Hora 8:58 Hora 8:59 Hora 9:0 Hora 9:1 Hora 9:2
Necesitamos unos ceros al principio para poder mostrar los números como se ven en los relojes. En lugar de emplear 2 para el ancho de campo, utiliza 02. Esto rellenará el campo con ceros en lugar de con espacios.
for horas in range(1, 13): for minutos in range(0, 60): print( "Hora {:02}:{:02}".format(horas, minutos) )
Hora 08:56 Hora 08:57 Hora 08:58 Hora 08:59 Hora 09:00 Hora 09:01 Hora 09:02
20.4 Números en Coma Flotante (Reales)
También podemos controlar los resultados en coma flotante. Examina el siguiente código y su salida:
x = 0.1 y = 123.456789 print("{:.1} {:.1}".format(x,y)) print("{:.2} {:.2}".format(x,y)) print("{:.3} {:.3}".format(x,y)) print("{:.4} {:.4}".format(x,y)) print("{:.5} {:.5}".format(x,y)) print("{:.6} {:.6}".format(x,y)) print() print("{:.1f} {:.1f}".format(x,y)) print("{:.2f} {:.2f}".format(x,y)) print("{:.3f} {:.3f}".format(x,y)) print("{:.4f} {:.4f}".format(x,y)) print("{:.5f} {:.5f}".format(x,y)) print("{:.6f} {:.6f}".format(x,y))
0.1 1e+02 0.1 1.2e+02 0.1 1.23e+02 0.1 123.5 0.1 123.46 0.1 123.457 0.1 123.5 0.10 123.46 0.100 123.457 0.1000 123.4568 0.10000 123.45679 0.100000 123.456789
Un formato del tipo .2 significa que el número será mostrado con una precisión de dos dígitos. Lamentablemente, esto quiere decir, que si mostramos el número 123, que tiene tres cifras significativas, en lugar de redondearlo, lo imprimirá en notación científica: 1.2e+02.
Un formato del tipo .2f (observa la f) quiere decir que mostremos el número con dos dígitos después del punto/coma decimal. De forma que 1 aparecerá como 1.00 y 1.5555 como 1.56.
También podemos especificar un carácter de ancho de campo en el programa:
x = 0.1 y = 123.456789 print("'{:10.1}' '{:10.1}'".format(x,y)) print("'{:10.2}' '{:10.2}'".format(x,y)) print("'{:10.3}' '{:10.3}'".format(x,y)) print("'{:10.4}' '{:10.4}'".format(x,y)) print("'{:10.5}' '{:10.5}'".format(x,y)) print("'{:10.6}' '{:10.6}'".format(x,y)) print() print("'{:10.1f}' '{:10.1f}'".format(x,y)) print("'{:10.2f}' '{:10.2f}'".format(x,y)) print("'{:10.3f}' '{:10.3f}'".format(x,y)) print("'{:10.4f}' '{:10.4f}'".format(x,y)) print("'{:10.5f}' '{:10.5f}'".format(x,y)) print("'{:10.6f}' '{:10.6f}'".format(x,y))
El formato 10.2f no significa que sean 10 dígitos antes y dos después del punto/coma decimal. Indica un ancho de campo total de 10. De esta forma, habrán 7 dígitos antes del punto/coma decimal, el punto/coma contará como uno más, y dos dígitos después.
' 0.1' ' 1e+02' ' 0.1' ' 1.2e+02' ' 0.1' ' 1.23e+02' ' 0.1' ' 123.5' ' 0.1' ' 123.46' ' 0.1' ' 123.457' ' 0.1' ' 123.5' ' 0.10' ' 123.46' ' 0.100' ' 123.457' ' 0.1000' ' 123.4568' ' 0.10000' ' 123.45679' ' 0.100000' '123.456789'
20.5 Imprimir Dólares y Centavos
Si quieres usar un punto/coma para los precios, puedes usar una f.Observa:
precio1 = 3.07 impuesto1 = precio1 * 0.06 total1 = precio1 + impuesto1 print("Precio: ${0:5.2f}".format(precio1) ) print("Impuesto: {0:5.2f}".format(impuesto1) ) print("------------") print("Total: ${0:5.2f}".format(total1) )
¡Recuerda! Sería más fácil pensar que %5.2f significaría 5 dígitos, un punto/coma, seguido de dos dígitos. Pero no es así, Esto indica un ancho de campo total de 5, incluyendo el punto/coma decimal y los dos dígitos siguientes. Ésta es la salida:
Precio: $ 3.07 Impuesto: 0.18 ------------ Total: $ 3.25
Peligro, cuando trabajamos con transacciones financieras, el código anterior tiene un error muy común ¿Puedes verlo? Intenta hacerlo con el código expandido siguiente:
precio1 = 3.07 impuesto1 = precio1 * 0.06 total1 = precio1 + impuesto1 print("Precio: ${0:5.2f}".format(precio1)) print("Impuesto: {0:5.2f}".format(impuesto1)) print("------------") print("Total: ${0:5.2f}".format(total1)) precio2 = 5.07 impuesto2 = precio2 * 0.06 total2 = precio2 + impuesto2 print() print("Precio: ${0:5.2f}".format(precio2)) print("Impuesto: {0:5.2f}".format(impuesto2)) print("------------") print("Total: ${0:5.2f}".format(total2)) print() gran_total = total1 + total2 print("Gran total: ${0:5.2f}".format(gran_total))
Ésta es la salida:
Precio: $ 3.07 Impuesto: 0.18 ------------ Total: $ 3.25 Precio: $ 5.07 Impuesto: 0.30 ------------ Total: $ 5.37 Gran total: $ 8.63
¿Localizas el error? ¡Tienes que vigilar los errores de redondeo! Observa el ejemplo, pareciera que el total debiera ser $ 8.62, pero no es así. El formato de impresión no modifica el número, sólo el resultado! Si modificamos el formato de impresión para que incluya tres dígitos después del punto/coma decimal, la razón del error aparecerá más claramente:
Precio: $3.070 Impuesto: 0.184 ------------ Total: $3.254 Precio: $5.070 Impuesto: 0.304 ------------ Total: $5.374 Gran total: $8.628
Una vez más, el formato de visualización no cambia el número. Debes usar el comando round para cambiar el valor y redondearlo verdaderamente. Observa:
precio1 = 3.07 impuesto1 = round(precio1 * 0.06,2) total1 = precio1 + impuesto1 print("Precio: ${0:5.2f}".format(precio1)) print("Impuesto: {0:5.2f}".format(impuesto1)) print("------------") print("Total: ${0:5.2f}".format(total1)) precio2 = 5.07 impuesto2 = round(precio2 * 0.06,2) total2 = precio2 + impuesto2 print() print("Precio: ${0:5.2f}".format(precio2)) print("Impuesto: {0:5.2f}".format(impuesto2)) print("------------") print("Total: ${0:5.2f}".format(total2)) print() gran_total = total1 + total2 print("Gran total: ${0:5.2f}".format(gran_total))
Precio: $ 3.07 Impuesto: 0.18 ------------ Total: $ 3.25 Precio: $ 5.07 Impuesto: 0.30 ------------ Total: $ 5.37 Gran total: $ 8.62
El comando round controla cuántos dígitos después del punto/coma decimal debemos redondear. Nos devuelve el valor redondeado pero sin cambiar el valor original. Observa:
x = 1234.5678 print(round(x, 2)) print(round(x, 1)) print(round(x, 0)) print(round(x, -1)) print(round(x, -2))
Observa debajo para que veas, cómo, el modo en que alimentamos la función round() con valores como -2, para el número de dígitos luego del punto/coma decimal, afecta al resultado:
1234.57 1234.6 1235.0 1230.0 1200.0
20.6 Su Uso en Pygame
No tenemos que usar el formateo de cadenas solo para declaraciones de impresión. El ejemplo timer_es.py utiliza formateo de cadena para volcar en pantalla un texto que simula un reloj:
# Usamos el formateo de cadenas de Python para añadir ceros al principio cadena_de_salida = "Hora: {0:02}:{1:02}".format(minutos,segundos) # Lo volcamos en la pantalla texto = font.render(cadena_de_salida, True, NEGRO) screen.blit(texto, [250, 250])
20.7 Repaso
20.7.1 Test
Haz click para ir a los Ejercicios.
You are not logged in. Log in here and track your progress.
English version by Paul Vincent Craven
Spanish version by Antonio Rodríguez Verdugo
Russian version by Vladimir Slav
Turkish version by Güray Yildirim
Portuguese version by Armando Marques Sobrinho and Tati Carvalho
Dutch version by Frank Waegeman
Hungarian version by Nagy Attila
Finnish version by Jouko Järvenpää
French version by Franco Rossi
Korean version by Kim Zeung-Il
Chinese version by Kai Lin