Занятие № 6. Применение строк для решения задач

Цель: изучить особенности реализации строк в Python; научиться применять строки при решении задач.

Теория

Строковые литералы

Строка - это последовательность пронумерованных символов. Строковые значения в Python имеют тип str. Чтобы записать строковый литерал используются одиночные и двойные кавычки:

name = 'Иван'
last_name = "Иванов"
print(name, last_name)

      
name = 'Иван'
last_name = "Иванов"
print(name, last_name)

Если заключить строковый литерал в тройные кавычки, то сохраняется форматирование строк и отступов:

code = """
for i in range(1, 10):
    if i == 5:
        continue
    print(i)
"""
print(code)

      
code = """
for i in range(1, 10):
    if i == 5:
        continue
    print(i)
"""
print(code)

Если использовать в примере выше одиночные кавычки, то произойдёт ошибка. Python сообщит, что в строке не хватает закрывающей кавычки.

Оператор индексирования строки

Каждый символ в строке обладает порядковым номером - индексом. Нумерация символов начинается с 0 (слева направо). Отсчёт символов также идёт и справа налево, но уже с помощью отрицательных чисел. В таком случае индекс последнего символа строки равен -1. Рисунок 1 показывает пример расстановки индексов в строке Язык Python:

Рисунок 1: Пример строки с индексами

Чтобы обратиться к символу по его индексу используется оператор индексирования [<индекс>]:

msg = "Язык Python"
print(msg[2])   # берём третий слева символ
print(msg[-4])  # берём четвертый справа символ

      
msg = "Язык Python"
print(msg[2])   # берём третий слева символ
print(msg[-4])  # берём четвертый справа символ

Обращение к символу по индексу создаёт новое значение типа str, содержащее один символ. В Python нет отдельного типа для хранения символов.

Значения в строковом типе - не изменяемы. Нельзя заменить отдельные символы, обратившись к ним по индексу:

msg = "Кот"
msg[1] = "и" # ошибка!

      
msg = "Кот"
msg[1] = "и" # ошибка!

В квадратных скобках может быть любое выражение, результатом вычисления которого будет целое число:

Что будет выведено на экран в результате выполнения следующего кода:

msg = "Язык Python"
print(msg[8])

Рисунок 1 подскажет правильный ответ.

Правильно. Отсчёт индексов начинается с нуля.

Отсчёт индексов начинается с 0 а не 1.

Выражение msg[-8] вернуло бы нам букву к. Но в примере индекс - положительное число.

В этом коде нет синтаксических ошибок.

Длина строки

Под длинной строки будем понимать количество символов в ней, включая пробелы. Чтобы узнать длину строки можно использовать функцию len():

st = "Язык Python"
print(len(st))

      
st = "Язык Python"
print(len(st))

Чтобы получить последний символ строки, хотелось бы записать:

st = "Язык Python"
st[len(st)] # возникнет ошибка!

      
st = "Язык Python"
st[len(st)] # возникнет ошибка!

но это приведёт к ошибке. Длина строки Язык Python равна x , а индекс последнего символа равен x . Возникает ошибка выхода значения индекса за границу допустимых значений. Чтобы получить последний символ строки нужно из длины строки вычесть 1 или обращаться по индексу -1:

st = "Язык Python"
last = st[len(st) - 1]
print(last)
last = st[-1]
print(last)

      
st = "Язык Python"
last = st[len(st) - 1]
print(last)
last = st[-1]
print(last)

В некоторых случаях может понадобиться получить символ стоящий в середине строки. Для этого понадобится оператор целочисленного деления //:

st = "Язык Python"
print(st[len(st) // 2])

      
st = "Язык Python"
print(st[len(st) // 2])

Стоит учитывать, что строка может быть пустой. В таком случае, её длина будет равна 0:

empty = "" # пустая строка
print(len(empty))

      
empty = "" # пустая строка
print(len(empty))

Оператор получения среза

Для того, чтобы получить подстроку в Python используется оператор среза - [<начало>:<конец>]. Внутри оператора указывается начальный индекс подстроки и, через двоеточие, индекс символа, до которого проходит срез (не включая сам символ).

writers = "Ильф и Петров"
print(writers[0:4])
print(writers[7:13])

      
writers = "Ильф и Петров"
print(writers[0:4])
print(writers[7:13])

Если не указать <начало> или <конец> среза, то копирование строки начнётся с первого или до последнего символа соответственно:

writers = "Ильф и Петров"
print(writers[:4])
print(writers[7:])

      
writers = "Ильф и Петров"
print(writers[:4])
print(writers[7:])

Если пропустить и <начало> и <конец>, то получим копию строки:

writers = "Ильф и Петров"
print(writers)
copy = writers[:] # сохраняем копию строки
print(copy)

      
writers = "Ильф и Петров"
print(writers)
copy = writers[:] # сохраняем копию строки
print(copy)

Что будет выведено на экран в результате выполнения следующего кода:

s = "Умному достаточно"
print(s[7:10])

Правильно. Мы получаем срез начиная с символа с индексом 7 и заканчивая индексом 9.

Для этого мы бы записали s[8:13].

Когда внутри [] два числа, значит мы хотим получить срез строки. Если число одно - получаем символ с этим индексом.

Для этого мы бы записали s[0:6] или s[:6] .

На самом деле, внутри [] может быть три значения, разделённых :. Это будет общая форма записи оператора среза: [<начало>:<граница>:<шаг>]. Последнее значение определяет с каким шагом нужно брать символы из строки:

word = 'тшеикфсрт'

# берём символы начиная с первого и до конца строки через 1
first = word[0::2]
# берём символы начиная со второго и до конца строки через 1
second = word[1::2]

print(first)
print(second)

      
word = 'тшеикфсрт'

# берём символы начиная с первого и до конца строки через 1
first = word[0::2]
# берём символы начиная со второго и до конца строки через 1
second = word[1::2]

print(first)
print(second)

Конкатенация и повторение строк

К строковым значениям применимы два арифметических оператора - сложение и умножение.

Сложение строковых значений называется конкатенацией:

name = "Иван"
last_name = "Иванов"
print(name + " " + last_name)

      
name = "Иван"
last_name = "Иванов"
print(name + " " + last_name)

При сложении нельзя смешивать значения разных типов:

print("Год: " + 2024) # Возникнет ошибка

      
print("Год: " + 2024) # Возникнет ошибка

Числа нужно явно преобразовать в строковый тип функцией str():

print("Год: " + str(2024))

      
print("Год: " + str(2024))

Если умножить строку на число, будет создана новая строка, в которой оригинал повторяется указанное количество раз:

print("-#-" * 5)

      
print("-#-" * 5)

В этом примере получится новая строка длиной в x символов.

Оператор принадлежности in

С помощью оператора in можно выяснить входит ли подстрока в строку:

st = "Привет"
print("ри" in st)
print("по" in st)

      
st = "Привет"
print("ри" in st)
print("по" in st)

Результат работы оператора - логическое значение. Если добавить перед in логический оператор not, то мы проверим, что подстрока не входит в строку:

st = "Привет"
print("вет" not in st)

      
st = "Привет"
print("вет" not in st)

Например, после вычисления выражения "кот" not in "Кот в мешке" мы получим значение x True, так как есть разница между строчными и прописными буквами.

Методы класса str

Все строковые значения являются объектами класса str. В этом можно убедится с помощью функции type(), которая возвращает тип аргумента:

s = "Скрипт"
print(type(s))

      
s = "Скрипт"
print(type(s))

Класс str обладает рядом методов, которые упрощают обработку строк.

Таблица 1: Некоторые методы класса str
Метод Назначение
s.count(sub) Количество вхождений подстроки sub в строку s
s.find(sub) Находит индекс первого вхождения подстроки sub в строку s
s.replace(old, new) Заменяет подстроку old на new; возвращает новую строку
s.upper() Преобразование всех символов в прописные; возвращает новую строку
s.lower() Преобразование всех символов в строчные; возвращает новую строку

Вот примеры использования этих методов:

s = "целым овладевают по частям"
print(s.count('a')) # количество букв 'а' в строке
print(s.find('по')) # индекс первого вхождения подстроки 'по'
s_new = s.replace(" ", "-*-") # меняем пробелы на '-*-'
print(s_new)
s_big = s.upper() # делаем все буквы прописными
print(s_big)

      
s = "целым овладевают по частям"
print(s.count('a')) # количество букв 'а' в строке
print(s.find('по')) # индекс первого вхождения подстроки 'по'
s_new = s.replace(" ", "-*-") # меняем пробелы на '-*-'
print(s_new)
s_big = s.upper() # делаем все буквы прописными
print(s_big)

Все инструкции и операторы для обработки строковых значений находятся в следующей таблице:

Таблица 2: Инструкции и операторы для обработки строк
Инструкции и операторы Назначение
+ Конкатенация
* Повторение
<строка>[] Индексирование
<строка>[ : ] Срез
len(<строка>) Длина строки
in, not in Нахождение в строке
for <символ> in <строка> Перебор символов
 

Какое значение будет хранится в переменной ty после выполнения следующего кода:

qu = "wow, welcome week!"
ty = qu.find("we")

Правильно. Когда мы ищем строку больше чем из одного символа, метод find вернёт нам индекс первого символа из найденной подстроки.

Когда мы ищем строку больше чем из одного символа, метод find вернёт нам индекс первого символа из найденной подстроки а не последнего.

Метод find вернёт индекс первого вхождения подстроки. Поиск происходит слева направо.

Метод find вернёт индекс первого вхождения подстроки. Поиск происходит слева направо.

В этом коде нет синтаксических ошибок.

Что будет выведено на экран в результате выполнения следующего кода:

title = "Колыбель для кошки"
title.upper()
print(title)

Верно. Вызов метода title.upper() вернёт новую строку с прописными буквами. Это строку мы не сохранили. Исходная строка в переменной title не поменялась. Исправленная программа:

title = "Колыбель для кошки"
title = title.upper() # сохраняем исправления
print(title)

Мы вызываем метод upper(), который делает все буквы прописными. Но будет ли сохранён результат этих изменений?

Такой результат мог бы получиться, если использовать метод lower(), который делает все буквы строчными.

В этом коде нет синтаксической ошибки, но есть семантическая.

После ответа на все вопросы становятся доступны кнопки перехода между вопросами.

Примеры

Пример № 1 (ex01.py)

По введённым имени и фамилии сгенерируйте логин пользователя. Логин формируется из первой буквы имени и первых семи букв фамилии.

# вводим имя и фамилию
first = input("Введите имя: ")
last = input("Введите фамилию: ")

# преобразуем все буквы к строчным с помощью метода lower()
first = first.lower()
last = first.lower()

# с помощью "среза" и конкатенации формируем ответ
uname = first[0] + last[:7]
print("Имя пользователя:", uname)

      
# вводим имя и фамилию
first = input("Введите имя: ")
last = input("Введите фамилию: ")

# преобразуем все буквы к строчным с помощью метода lower()
first = first.lower()
last = first.lower()

# с помощью "среза" и конкатенации формируем ответ
uname = first[0] + last[:7]
print("Имя пользователя:", uname)

Пример № 2 (ex02.py)

Определите день недели по его номеру.

days = "ПнВтСрЧтПтСбВс" # строка с днями недели
num = int(input("Введите номер: "))

# вычисляем позицию, с которой начинается подстрока
pos = (num - 1) * 2

# получаем "срез" строки
day = days[pos:pos + 2]
print("День недели:", day)

      
days = "ПнВтСрЧтПтСбВс" # строка с днями недели
num = int(input("Введите номер: "))

# вычисляем позицию, с которой начинается подстрока
pos = (num - 1) * 2

# получаем "срез" строки
day = days[pos:pos + 2]
print("День недели:", day)

Пример № 3 (ex03.py)

Закодируйте введённую строку, заменив буквы на ASCII-коды. Числа разделите пробелом.

message = input("Какое сообщение закодировать? ")

output = "" # инициализируем пустую строку-аккумулятор

# в цикле for перебираем все символы сообщения
for ch in message:
    ch_code = ord(ch) # получаем числовой код символа

    # обновляем значение аккумулятора, прибавляя код символа и пробел
    output = output + str(ch_code) + " "

print("Закодированное сообщение: ", output)

      
message = input("Какое сообщение закодировать? ")

output = "" # инициализируем пустую строку-аккумулятор

# в цикле for перебираем все символы сообщения
for ch in message:
    ch_code = ord(ch) # получаем числовой код символа

    # обновляем значение аккумулятора, прибавляя код символа и пробел
    output = output + str(ch_code) + " "

print("Закодированное сообщение: ", output)

Задания для самостоятельной работы

Задание № 1 (sam01.py)

Напишите программу, которая просит пользователя ввести слово, а затем выводит буквы этого слова с новой строки столько раз, сколько букв в самом слове.

Пример:

Введите слово: окно
оооо
кккк
нннн
оооо

Используйте цикл for, чтобы перебирать символы введённой строки.

Длину строки можно узнать с помощью функции len(). Это и будет количество повторений буквы.

Умножая строку на число, мы повторим её нужное количество раз. Каждую букву слова нужно умножить на длину всей строки.

# ввод строки
s = input("Введите строку: ")

# сохраняем длину строки
d = len(s)

# перебираем символы строки
for letter in s:
    # умножаем букву на длину строки
    print(letter * d)

Задание № 2 (sam02.py)

Пользователь вводит несколько слов через пробел. Посчитайте количество слов и выведите его на экран. Между словами ставится один пробел.

Пример:

Введите предложение: Сегодня мы изучаем язык программирования Python
Слов в предложении: 6

Обратите внимание на пример. Сколько слов в строке? Сколько пробелов в строке?

Нужно посчитать количество пробелов в строке. Найдите в Таблица 1 подходящий для этого метод.

Что будет, если ввести пустую строку. Учтите этот вариант с помощью инструкции ветвления.

# ввод строки
st = input("Введите строку")

# проверим введена ли пустая строка
if len(st) == 0:
    print("Введена пустая строка")
else:
    # находим количество пробелов и прибавляем 1
    num = st.count(" ") + 1
    print("Слов в преложении:", num)

Задание № 3 (sam03.py)

Пользователь вводит свои имя и фамилию через пробел. Программа выводит на экран инициалы пользователя. Учтите тот факт, что имя и фамилия могут быть написаны с маленькой буквы, а инициалы всегда пишутся с большой буквы.

Примеры:

Введите имя и фамилию: Петров Иван
Ваши инициалы - П.И.
Введите имя и фамилию: сидоров петр
Ваши инициалы - С.П.

Задание № 4 (sam04.py)

Создайте программу, с помощью которой можно заменить одно слово на другое.

Пользователь вводит строку со словами разделёнными пробелом. После этого программа запрашивает у пользователя слово, которое нужно заменить и слово для замены. После замены, программа выводит новую строку и количество произведённых замен.

Пример:

Введите строку: он сегодня работает? нет, он сегодня отдыхает
Какое слово заменить? он
Каким словом заменить? Саша
Результат: Саша сегодня работает? нет, Саша сегодня отдыхает
Количество замен: 2

Задание № 5 (sam05.py)

Напишите программу, которая получив от пользователя положительное целое число находит сумму его цифр.

Пример:

Введите число: 3582
Сумма цифр числа 3582 - 18

Дополнительный плюс, если ответ будет выводиться в следующем формате:

Введите число: 3582
Сумма цифр: 3+5+8+2=18

Задание № 6 (sam06.py)

Пользователь вводит строку в которой встречаются строчные и прописные буквы. Измените исходную строку таким образом, чтобы строчные буквы стали прописными и наоборот. Введённая строка может содержать пробелы и знаки препинания, которые должны остаться без изменения.

Пример:

Исходная строка: ПРивЕт, кАК деЛА?
Ответ: прИВеТ, Как ДЕла?
Полезные методы

Для решения вам пригодятся методы isupper() и islower(). Для подробностей смотрите справочник.

Задание № 7 (sam07.py)

Палиндромом называется слово или фраза, которое читается одинаково в обоих направлениях (примеры: топот, шалаш и т.д.).

Пользователь вводит строку. Ваша программа должна определить является ли она палиндромом.

Примеры:

Введите строку: шалаш
Введённая строка - палиндром
Введите строку: сочетание
Введённая строка не палиндром

Задание № 8 (sam08.py)

Пользователь вводит друг за другом два слова. Программа должна определить, можно ли из букв слова с наибольшим количеством букв, составить слово с наименьшим количеством букв.

Примеры:

Введите первое слово: око
Введите второе слово: окно
Из слова окно можно составить слово око
Введите первое слово: программа
Введите второе слово: строка
Составить нельзя