Строки и форматирование
Вывод на экран
Вы уже умеете выводить на экран текст, складывая строки. А вот как напечатать без этого? Нужно в скобках функции print() перечислить через запятую аргументы, которые она печатает:
weather = 'облачно'
print('На улице сейчас', weather) # На улице сейчас облачно
2
Запятая между аргументами по умолчанию заменяется на пробел.
print('За', 'окном', 'метель') # За окном метель
Это значит, что в сообщения можно не добавлять пробелы, когда составляете сложную фразу. Достаточно разделить аргументы функции print()
запятой. И, что приятно, количество этих аргументов не ограничено:
messages_count = 12
print('У тебя', messages_count, 'новых сообщений.') # У тебя 12 новых сообщений.
2
Упражнения
- Продолжим учить Виту вести беседы о погоде. Напечатайте на экран данные из списка
weather_today
в формате'Сегодня гроза и на градуснике 21'
. Вместо сложения строк и приведения чисел к строкам просто перечислите аргументы в скобках функцииprint()
.
weather_today = [[19, 'дождь'], [22, 'облачно'], [24, 'солнечно']]
for weather in weather_today:
print(...) # измените код
2
3
4
Метод split()
Разбить фразу на слова, и вообще разделить строку по определённому символу можно методом split()
(англ. «разделить»). В результате получится список строк. Метод split()
принимает аргумент, указывающий, какой разделитель использовать.
blok_string = 'Ночь. Улица. Фонарь. Аптека'
# из строки получаем список, где строку делят по сочетанию точки и пробела:
blok_list = blok_string.split('. ')
print(blok_list) # ['Ночь', 'Улица', 'Фонарь', 'Аптека']
# можно заказать, к примеру, последнее слово:
print(blok_list[-1]) # Аптека
2
3
4
5
6
Замечание. Да, Python позволяет использовать отрицательные индексы для обращения к элементам списка. При этом -1
соответствует последнему элементу, -2
— предпоследнему, и т.д. В общем случае, blok_list[-k]
— это то же самое, что blok_list[len(blok_list) - k]
, только короче. Например, если нужен пятый символ с конца списка s
, можно написать s[len(s) - 5]
или, короче, s[-5]
. Если в вызове split()
не указывать разделитель, то строка разобьётся по пробелам:
blok_string = 'Ночь. Улица. Фонарь. Аптека.'
# из строки получаем список:
blok_list = blok_string.split()
print(blok_list) # ['Ночь.', 'Улица.', 'Фонарь.', 'Аптека.']
2
3
4
Тогда появятся лишние точки на концах слов. Их удобнее всего убирать методом strip()
— он убирает указанные символы в начале и в конце.
# хотим "Ночь" без точки
print(blok_list[0].strip('.')) # Ночь
2
Упражнения
- Имеется список запросов
queries
. Необходимо определить, какие из них адресованы Вите, а какие — другим людям. Напишите функциюcheck_query()
, которая принимает запрос как параметр, анализирует его и возвращает один из двух вердиктов:
- строку 'запрос к Вите', если запрос начинается с обращения к Вите,
- строку 'запрос к кому-то ещё', если нет.
Код вывода результатов на экран уже написан в основном теле программы.
def check_query(query):
# напишите код тела функции
...
# дальше следует код, вызывающий вашу функцию; не изменяйте его:
queries = [
'Вита, сколько у меня друзей?',
'Андрей, ну где ты был?',
'Андрей, ну обними меня скорей!',
'Вита, кто все мои друзья?'
]
for q in queries:
result = check_query(q)
print(q, '-', result)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- Вы умеете звать Виту. Теперь надо научить её распознавать суть запроса. Отделите обращения — перепишите функцию
check_query()
так, чтобы она возвращала: Например, для запроса 'Вита, сколько у меня друзей?' верните строку 'сколько у меня друзей?'. Для запроса 'Серёга, ты где?' — строку 'ты где?'. У строки, которую она возвращает, не должно быть пробелов в начале и конце.
def check_query(query):
# напишите код тела функции
...
# дальше следует код, вызывающий вашу функцию; не изменяйте его:
queries = [
'Вита, сколько у меня друзей?',
'Андрей, ну где ты был?',
'Андрей, ну обними меня скорей!',
'Вита, кто все мои друзья?'
]
for q in queries:
result = check_query(q)
print(q, '-', result)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Форматирование строк
До сих пор для вывода текста на экран вам приходилось собирать его из нескольких частей. Но есть и другой способ. Для сборки текста из разных элементов удобны f-строки
(от англ. formatted string, «форматированные строки»). Эти f-строки
включают имена переменных внутри фигурных скобок. Значения переменных подставляются в строку автоматически. В коде f-строки
выглядят как обычные, только начинаются с символа f
перед кавычками:
weather = 'облачно'
print(f'На улице сейчас {weather}.')
# Сравните с
# print('На улице сейчас ' + weather + '.')
# или
# print('На улице сейчас', weather, '.') — в таком коде не убрать пробел перед точкой
2
3
4
5
6
7
Результат вывода:
На улице сейчас облачно.
Преобразование типов из числа в строку f-строки проделывают автоматически:
one_hundred = 100
rubles = 'рублей'
friends = 'друзей'
print(f'Не имей {one_hundred} {rubles}, а имей {one_hundred} {friends}.')
# Это проще и понятнее, чем написать
# print('Не имей ' + str(one_hundred) + ' ' + rubles + ', а имей ' + str(one_hundred) +' ' + friends + '.')
2
3
4
5
6
7
Результат вывода:
Не имей 100 рублей, а имей 100 друзей.
Упражнения
- Замените объединение строк на f-строку.
def show_meteo(temperature, weather):
print('Сейчас ' + weather + ', на градуснике ' + str(temperature) + '.')
show_meteo(24, 'облачно')
2
3
4
- В коде финальной задачи из темы «Циклы и ветвления» замените все объединения строк на f-строки.
def format_text(messages_count):
remainder = messages_count % 10
if messages_count == 0:
return 'нет новых сообщений'
elif remainder == 0 or remainder >= 5 or (10 <= messages_count <= 19):
return messages_count + 'новых сообщений'
elif remainder == 1:
return messages_count + 'новое сообщение'
else:
return messages_count + 'новых сообщения'
def print_count(messages_count):
text = format_text(messages_count)
print('У вас', text, '.')
print_count(0)
print_count(1)
print_count(4)
print_count(5)
print_count(12)
print_count(22)
print_count(25)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Подробнее о форматировании
В f-строки
можно подставлять не только переменные, но и результаты вычислений. Например, арифметические операции:
one_hundred = 100
five_hundred = 500
print(f'{one_hundred} + {five_hundred} = {one_hundred + five_hundred}')
one_hundred = 'сто'
five_hundred = 'пятьсот'
print(f'{one_hundred} + {five_hundred} = {one_hundred + five_hundred}')
2
3
4
5
6
7
Результат вывода:
100 + 500 = 600
сто + пятьсот = стопятьсот
2
И обращение к элементам списка:
russian_alphabet = ['а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я']
print(f'"{russian_alphabet[-1]}" - последняя буква в алфавите.')
2
3
Результат вывода:
"я" - последняя буква в алфавите.
А также к элементам словаря по ключу:
favorite_songs = {
'Тополиный пух': 'Иванушки international',
'Город золотой': 'Аквариум',
'Звезда по имени Солнце': 'Кино'
}
song = 'Город золотой'
print(f'"{song}" - одна из известных пеcен группы "{favorite_songs[song]}".')
2
3
4
5
6
7
8
9
Результат вывода:
"Город золотой" - одна из известных пеcен группы "Аквариум".
Хоть Python и позволяет вставлять очень сложные выражения внутрь f-строк
, не злоупотребляйте этой возможностью. Иначе получится перегруженный код, в котором будет сложно разобраться. Сравните два эквивалентных примера:
print(f'Корни уравнения равны {(-b + (b**2 - 4*a*c)**(1/2)) / (2*a)} и {(-b - (b**2 - 4*a*c)**(1/2)) / (2*a)}')
и
d = b**2 - 4*a*c
x1 = (-b + d**(1/2)) / (2*a)
x2 = (-b - d**(1/2)) / (2*a)
print(f'Корни уравнения равны {x1} и {x2}')
2
3
4
Второй намного понятнее, хотя строк стало в четыре раза больше. Не так ли? Лучше придерживаться общего правила: f-строки
используются только для форматирования вывода, а вычислять все выражения надо вне их. И вообще, не стоит экономить на количестве строчек кода, принося в жертву его читаемость.
Упражнения
- Научите Виту сообщать время в формате ЧЧ:ММ:СС (часы, минуты, секунды). Например
На часах 19:28:06
.
def print_time(hour, minute, second):
print(...) # аргумент должен содержать f-строку
print_time('19', '28', '06')
2
3
4
- Вите передали список
listened
(англ. listen, "слушать") с хронометражем прослушанных песен в секундах. Выведите на экран суммарную статистику: 'Вы прослушали N песен.', где N — длина спискаlistened
.
def calc_stat(listened): # от англ. calculate statistics, посчитать статистику
# напишите код функции
print(calc_stat([193, 148, 210, 144, 174, 159, 163, 189, 230, 204]))
2
3
4
- Вите передали список
listened
(англ. listen, "слушать") с хронометражем прослушанных песен в секундах. Выведите на экран суммарную статистику:
'Вы прослушали N песен, общей продолжительностью M минут и S секунд.'
где:
- N — длина списка
listened
; - M — количество целых минут общей продолжительности прослушанного;
- S — остаток от целых минут.
def calc_stat(listened): # от англ. calculate statistics, посчитать статистику
# напишите код функции
print(calc_stat([193, 148, 210, 144, 174, 159, 163, 189, 230, 204]))
2
3
4
Запросы к друзьям
В предыдущей теме «Словари и множества» вы добавили в код персонального ассистента Виты данные о том, где живут ваши друзья. И она уже умеет отвечать на следующие запросы:
- Сколько у меня друзей?
- Кто все мои друзья?
- Где все мои друзья?
Сейчас вам предстоит расширить возможности Виты. Научить её отвечать на вопросы про отдельных друзей. Начнём с самого простого вопроса «ты где?» — внутри Виты уже хранятся данные о местоположении. Если, например, Коля и Соня находятся в списке друзей, то запросы о них будет выглядеть следующим образом:
- Коля, ты где?
- Соня, ты где?
Чтобы различать вопросы про отдельных друзей от общих вопросов к Вите, будем начинать общие вопросы с прямого обращения, вот так:
- Вита, сколько у меня друзей?
- Вита, кто все мои друзья?
- Вита, где все мои друзья?
Тогда различать просто. Если вопрос начинается с имени "Вита", то это общий вопрос. А если с другого имени, то это вопрос про конкретного друга. Полагаем, правда, что у нас нет друзей по имени Вита. 😃
Упражнения
- Это код Виты, который вы последовательно писали на протяжении нескольких тем. Можете запустить его, вспомнить как выполняются запросы из списка
queries
.
DATABASE = {
'Сергей': 'Омск',
'Соня': 'Москва',
'Миша': 'Москва',
'Дима': 'Челябинск',
'Алина': 'Красноярск',
'Егор': 'Пермь',
'Коля': 'Красноярск'
}
def process_query(query):
# напишите код функции
def format_count_friends(count_friends):
if count_friends == 1:
return '1 друг'
elif 2 <= count_friends <= 4:
return f'{count_friends} друга'
else:
return f'{count_friends} друзей'
def process_vita(query):
if query == 'сколько у меня друзей?':
count_string = format_count_friends(len(DATABASE))
return f'У тебя {count_string}'
elif query == 'кто все мои друзья?':
friends_string = ', '.join(DATABASE.keys())
return f'Твои друзья: {friends_string}'
elif query == 'где все мои друзья?':
unique_cities = set(DATABASE.values())
cities_string = ', '.join(unique_cities)
return f'Твои друзья в городах: {cities_string}'
else:
return '<неизвестный запрос>'
def runner():
queries = [
'сколько у меня друзей?',
'кто все мои друзья?',
'где все мои друзья?',
'кто виноват?'
]
for query in queries:
print(query, '-', process_vita(query))
runner()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
А. Отредактируйте список запросов queries. Все запросы должны начинаться с обращения Вита:
- Вита, сколько у меня друзей?
- ...
Б. Напишите функцию process_query(query)
. Значение параметра query
должно быть обработано методом split()
. Отделите имя в начале от тела запроса (т.е., от оставшейся части).
Если запрос начинается с имени "Вита", то вызовите функцию process_anfisa()
, передав в неё тело запроса как параметр. И верните результат выполнения этой функции. Если запрос начинается с другого имени, то пока ничего не делайте — это отложим до следующей задачи.
В. Измените в функции runner()
вызов process_anfisa()
на вызов process_query()
.
- А. Напишите функцию
process_friend(name, query)
(англ. friend, "друг"), принимающую имя другаname
и запросquery
.
- Если друга с указанным именем
Н
нет в списке, то функция должна вернуть сообщение об ошибкеУ тебя нет друга по имени Н
. - Если запрос — "ты где?", то функция должна вернуть сообщения 'Н в городе Г', где Г определяется по данным словаря
DATABASE
. - Если запрос не "ты где?", а какой-то другой, то функция должна вернуть сообщение об ошибке <неизвестный запрос>.
Б. Допишите функцию process_query()
. Если запрос начинается не с "Вита", а с другого имени, то вызовите функцию process_friend(name, query)
, передав в неё имя друга и тело запроса. И верните результат выполнения этой функции.
В. Добавьте в список queries
новые запросы вида:
Коля, ты где?
Соня, что делать?
Антон, ты где?
DATABASE = {
'Сергей': 'Омск',
'Соня': 'Москва',
'Миша': 'Москва',
'Дима': 'Челябинск',
'Алина': 'Красноярск',
'Егор': 'Пермь',
'Коля': 'Красноярск'
}
def process_friend(name, query):
# напишите код функции
def process_query(query):
# напишите код функции
def format_count_friends(count_friends):
if count_friends == 1:
return '1 друг'
elif 2 <= count_friends <= 4:
return f'{count_friends} друга'
else:
return f'{count_friends} друзей'
def process_anfisa(query):
if query == 'сколько у меня друзей?':
count_string = format_count_friends(len(DATABASE))
return f'У тебя {count_string}'
elif query == 'кто все мои друзья?':
friends_string = ', '.join(DATABASE.keys())
return f'Твои друзья: {friends_string}'
elif query == 'где все мои друзья?':
unique_cities = set(DATABASE.values())
cities_string = ', '.join(unique_cities)
return f'Твои друзья в городах: {cities_string}'
else:
return '<неизвестный запрос>'
def runner():
queries = [
'Вита, сколько у меня друзей?',
'Вита, кто все мои друзья?',
'Вита, где все мои друзья?',
'Вита, кто виноват?',
'Коля, ты где?',
'Соня, что делать?',
'Антон, ты где?'
]
for query in queries:
print(query, '-', process_query(query))
runner()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52