Программирование аркадных игр
и обучение информатикеChapter 20: Форматирование
20.1 Десятичные числа
Попробуйте запустить следующую программу, выводящую на экран несколько случайных чисел.
import random for i in range(10): x=random.randrange(20) print(x)
Вывод выглядит ужасно: он выравнен по левому краю:
16 13 2 0 10 3 18 1 14 5
Мы можем использовать форматирование с помощью print, создав список чисел, выравненный по правому краю. Первым шагом будет использование команды format() на строке. Посмотрите ниже:
import random for i in range(10): x=random.randrange(20) print("{}".format(x) )
Вышеприведённый код не выравнивает числа по правому краю, но он принуждает программу к использованию форматирования. Посмотрите, как заканчиваются строки при команде .format(). Строка на самом деле является инстанцией класса и этот объект обладает методами, которые можно вызвать. Один из них это format().
Функция format() не выведет фигурные скобки. Вместо этого, она заменит {} на значение, сохранённое в x. Выводи (ниже) выглядит точно так же, как и раньше.
7 15 4 12 3 8 7 15 12 8
Для выравнивания по правому краю, надо добавить больше информации между фигурными скобками {}:
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
Так то лучше, мы выровняли числа! Но как это работает? { } говорят компьютеру о том, что мы будем форматировать число. После : внутри фигурных скобок, мы добавляет информацию по форматированию. Мы пишем 2 для задания длины поля в два символа. Длина поля говорит компьютеру, чтобы он попытался разместить число внутри поля длиной в 2 символа. По умолчанию, он будет стараться выравнивать числа по правому краю, а текст - по левому.
Ещё лучше, программе больше не нужно вызывать str( ) для конвертации числа в строку. Уберём конвертацию строк.
Что, если у нас числа побольше? Создадим список больших случайных чисел:
import random for i in range(10): x=random.randrange(100000) print( "{:6}".format(x) )
Это выдаёт нам вывод, выровнянный по правому краю, но всё ещё не выглядящий хорошо:
18394 72242 97508 21583 11508 76064 88756 77413 7930 81095
Где же разделители? Возьмём следующий пример чтобы увидеть, как они добавляются:
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
Запятая должна находится перед полем, обозначающим длину, но не после. Запятые учитываются при вычислении длины поля. Например, 1,024 обладает длиной в 5, а не 4.
Мы можем вывести несколько значений, скомбинировав их в текст. Запустите нижеприведённый код.
x=5 y=66 z=777 print ("A - '{}' B - '{}' C - '{}'".format(x,y,z) )
Программа заменит фигурные скобки числами, а также выведет весь другой текст строки:
A - '5' B - '66' C - '777'
Если задано три набора фигурных скобок, компьютер может ожидать все три значения перечисленными в команде format(). Первое число заменит первую фигурную скобку.
Иногда мы можем пожелать вывести одно и то же значение дважды. Или показать их в ином порядке, отличном от того, который был использован в функции format().
x=5 y=66 z=777 print ("C - '{2}' A - '{0}' B - '{1}' C again - '{2}'".format(x,y,z) )
Заметьте, что, размещая число внутри фигурных скобок, мы можем задать порядок выведения параметров, переданных функции format(). Нумерация параметров начинается с 0, так что x считается параметром 0.
Мы всё ещё можем задать форматирование информации после двоеточия. Например:
x=5 y=66 z=777 print ("C - '{2:4}' A - '{0:4}' B - '{1:4}' C again - '{2:4}'".format(x,y,z) )
Мы можем заметить, что вышеприведённый код покажет значения, выровненные по правому краю, длиной в четыре символа:
C - ' 777' A - ' 5' B - ' 66' C again - ' 777'
20.2 Строки
Далее посмотрим на форматирование строк. Также, положим несколько значений на одну линию. Следующий список выглядит отвратительно.
my_fruit = ["Apples","Oranges","Grapes","Pears"] my_calories = [4,300,70,30] for i in range(4): print(my_fruit[i],"are",my_calories[i],"calories.")
Apples are 4 calories. Oranges are 300 calories. Grapes are 70 calories. Pears are 30 calories.
Теперь попробуем использовать команду format. Заметьте, что мы можем добавить дополнительный текст и больше одного значения в одну строку.
my_fruit = ["Apples","Oranges","Grapes","Pears"] my_calories = [4,300,70,30] for i in range(4): print("{:7} are {:3} calories.".format(my_fruit[i],my_calories[i]) )
Apples are 4 calories. Oranges are 300 calories. Grapes are 70 calories. Pears are 30 calories.
Выглядит классно, точно так, как мы хотели. Но что, если мы не хотим, чтобы число было выровнено по правому краю, а текст - по левому? Мы можем использовать символы < и >, как это сделано в следующем примере:
my_fruit = ["Apples","Oranges","Grapes","Pears"] my_calories = [4,300,70,30] for i in range(4): print("{:>7} are {:<3} calories.".format(my_fruit[i],my_calories[i]) )
Apples are 4 calories. Oranges are 300 calories. Grapes are 70 calories. Pears are 30 calories.
20.3 Ведущие нули
Это создаёт неправильный вывод:
for hours in range(1,13): for minutes in range(0,60): print( "Time {}:{}".format(hours, minutes) )
Time 8:56 Time 8:57 Time 8:58 Time 8:59 Time 9:0 Time 9:1 Time 9:2
Нам нужно использовать ведущие нули для отображения чисел на часах. Вместо указания 2 для длинны поля, нужно использовать 02. Это заполнит поле нулями, вместо пробелов.
for hours in range(1,13): for minutes in range(0,60): print( "Time {:02}:{:02}".format(hours, minutes) )
Time 08:56 Time 08:57 Time 08:58 Time 08:59 Time 09:00 Time 09:01 Time 09:02
20.4 Числа с плавающей точкой
Мы также можем контролировать вывод с плавающей точкой. Оцените следующий код и его вывод:
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
Формат .2 обозначает отображение числа с точностью в две цифры. К сожалению, это значит, что если мы выведем число 123, которое обладает тремя цифрами, то вместо его округления мы получим его научную запись: 1.2e+02.
Формат .2f (заметьте f) значит отображение числа с двумя цифрами после запятой. Так что число 1 будет отображено как 1.00, а число 1.5555 выведется как 1.56.
Программа также может задать длинну поля:
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) )
Формат 10.2f не значит 10 цифр до дробной части и 2 после. Он означает общую длинну поля 10. Так что в итоге у нас будет 7 цифр до дробной части, разделитель, который считается ещё одним символом, и 2 символа в дробной части.
' 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 Вывод долларов и центов
Если вы хотите распечатать дробное число с ценой, вы можете использовать f. Ознакомьтесь с примером:
cost1 = 3.07 tax1 = cost1 * 0.06 total1 = cost1 + tax1 print("Cost: ${0:5.2f}".format(cost1) ) print("Tax: {0:5.2f}".format(tax1) ) print("------------") print("Total: ${0:5.2f}".format(total1) )
Помните! Легко подумать, что %5.2f будет означать пять цифр, дробный разделитель и затем ещё два символа. Но это не так. Это значит, что общая длинна поля - пять, включая дробный разделитель и две цифры после него. Вот вывод:
Cost: $ 3.07 Tax: 0.18 ------------ Total: $ 3.25
Осторожно! В вышеприведённом коде есть ошибка, частая в работе с финансовыми переводами. Можете ли вы её заметить? Попробуйте найти её в расширенном варианте кода нижнего примера:
cost1 = 3.07 tax1 = cost1 * 0.06 total1 = cost1 + tax1 print("Cost: ${0:5.2f}".format(cost1) ) print("Tax: {0:5.2f}".format(tax1) ) print("------------") print("Total: ${0:5.2f}".format(total1) ) cost2 = 5.07 tax2 = cost2 * 0.06 total2 = cost2 + tax2 print() print("Cost: ${0:5.2f}".format(cost2) ) print("Tax: {0:5.2f}".format(tax2) ) print("------------") print("Total: ${0:5.2f}".format(total2) ) print() grand_total = total1 + total2 print("Grand total: ${0:5.2f}".format(grand_total) )
Here's the output:
Cost: $ 3.07 Tax: 0.18 ------------ Total: $ 3.25 Cost: $ 5.07 Tax: 0.30 ------------ Total: $ 5.37 Grand total: $ 8.63
Заметили ошибку? Нужно опасаться ошибок с округлением. Посмотрите на этот пример. Кажется, что сумма должна быть $ 8.62, но это не так.
Формат вывода не меняет число, только вывод. Если мы поменяем форматирование вывода так, чтобы оно включало три знака в дробной части, причина ошибки становится более очевидной:
Cost: $3.070 Tax: 0.184 ------------ Total: $3.254 Cost: $5.070 Tax: 0.304 ------------ Total: $5.374 Grand total: $8.628
Опять же, форматирование вывода не меняет число. Используйте функцию round() для изменения значения и настоящего округления. Посмотрите дальше:
cost1 = 3.07 tax1 = round(cost1 * 0.06,2) total1 = cost1 + tax1 print("Cost: ${0:5.2f}".format(cost1) ) print("Tax: {0:5.2f}".format(tax1) ) print("------------") print("Total: ${0:5.2f}".format(total1) ) cost2 = 5.07 tax2 = round(cost2 * 0.06,2) total2 = cost2 + tax2 print() print("Cost: ${0:5.2f}".format(cost2) ) print("Tax: {0:5.2f}".format(tax2) ) print("------------") print("Total: ${0:5.2f}".format(total2) ) print() grand_total = total1 + total2 print("Grand total: ${0:5.2f}".format(grand_total) )
Cost: $ 3.07 Tax: 0.18 ------------ Total: $ 3.25 Cost: $ 5.07 Tax: 0.30 ------------ Total: $ 5.37 Grand total: $ 8.62
Команда округления контролирует, до скольки символов после запятой мы хотим округлить. Она возвращает округлённое значение, но не меняет оригинального значения. Посмотрим ниже:
x=1234.5678 print( round(x,2) ) print( round(x,1) ) print( round(x,0) ) print( round(x,-1) ) print( round(x,-2) )
Посмотрите ниже, чтобы разобраться, что случается, если функции round() подаются негативные значения вроде -2 для количества цифр после запятой:
1234.57 1234.6 1235.0 1230.0 1200.0
20.6 Применение в Pygame
Не обязательно использовать форматирование строк только для выражения print. Пример timer.py использует строчное форматирование и рисует результирующий текст на экране, создавая тем самым таймер:
# Используем форматирование строк в python для добавления ведущих нулей output_string = "Time: {0:02}:{1:02}".format(minutes,seconds) # Нарисовать на экране text = font.render(output_string,True,black) screen.blit(text, [250,250])
20.7 Проверка пройденного
- Возьмите следующую программу:
score=41237 highscore=1023407 print("Очки: "+str(score) ) print("Рекорд: "+str(highscore) )
Которая сейчас выводит:
Score: 41237 High score: 1023407
Используйте форматирование метода print так, чтобы вывод выглядел следующим образом:
Score: 41,237 High score: 1,023,407
- Создайте программу, идущая по циклу от 1 до 20 и выводящая, чему равно текущее число в минус первой степени.
Используйте форматирование метода print чтобы достигнуть следующего вывода:
1/1 = 1.0 1/2 = 0.5 1/3 = 0.333 1/4 = 0.25 1/5 = 0.2 1/6 = 0.167 1/7 = 0.143 1/8 = 0.125 1/9 = 0.111 1/10 = 0.1 1/11 = 0.0909 1/12 = 0.0833 1/13 = 0.0769 1/14 = 0.0714 1/15 = 0.0667 1/16 = 0.0625 1/17 = 0.0588 1/18 = 0.0556 1/19 = 0.0526 1/20 = 0.05
- Напишите рекурсивную функцию, которая будет вычислять числа фибоначчи, при этом
применяя форматирование вывода. Ваш результат должен выглядеть чем-то вроде:
1 - 0 2 - 1 3 - 1 4 - 2 5 - 3 6 - 5 7 - 8 8 - 13 9 - 21 10 - 34 11 - 55 12 - 89 13 - 144 14 - 233 15 - 377 16 - 610 17 - 987 18 - 1597 19 - 2584 20 - 4181 21 - 6765 22 - 10946 23 - 17711 24 - 28657 25 - 46368 26 - 75025 27 - 121393 28 - 196418 29 - 317811 30 - 514229 31 - 832040 32 - 1346269 33 - 2178309 34 - 3524578 35 - 5702887
- Почему оно выполняется так медленно? Как можно заставить его выполняться быстрее?
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