Урок №30. Обработка символьных данных.
Если в середине XX века первые компьютеры создавались, прежде всего, для выполнения сложных математических расчётов (например, для расчёта траекторий полёта ракет и снарядов), то сейчас они очень часто обрабатывают текстовую (символьную) информацию.
Символьная строка — это последовательность символов, которая рассматривается как единый объект. В языке Python строка относится к типу str (от английского string — строка). Проверить это можно следующей программой:
s = "Питон"
print( type(s) )
которая выведет
Cclass 'str'>Новое значение записывается в строку с помощью оператора присваивания (как выше) или функции ввода с клавиатуры:
s = input ()Встроенная функция lеn определяет длину строки — количество символов в ней. Вот так в переменную п записывается длина строки s:
n = len ( s )Строки можно сравнивать между собой так же, как числа. Например, можно проверить равенство двух строк:
password = input ( "Введите пароль:" )
if password == "sEzAm":
print ( "Слушаюсь и повинуюсь!" )
else:
print ( "No pasaran!" )
Можно также определить, какая из двух строк больше, какая — меньше. Если строки состоят только из русских или только из латинских букв, то меньше будет та строка, которая идёт раньше в алфавитном списке. Например, слово «паровоз» будет «меньше», чем слово «пароход»: они различаются в пятой букве и «б» < «х». Это можно проверить экспериментально, например с помощью такой программы:
si = "паровоз"
s2 = "пароход"
if si < s2:
print ( si, s2 )
elif si == s2:
print( si, s2 )
else:
print ( si, ">", s2 )
Но откуда компьютер «знает», что такое алфавитный порядок? При сравнении используются коды символов. В современных кодировках и русские, и английские буквы расположены в алфавитном порядке, т. е. код буквы «в» меньше, чем код буквы «х».
Оператор «+» используется для «сложения» (объединения, сцепления) строк. Эта операция иногда называется конкатенацией. Например:
hello = "Привет"
namе = "Пантелеймон"
greeting = hello + ", " + name + "!"
В результате в переменную greeting будет записано значение
"Привет, Пантелеймон!"В язык Python введена операция умножения строки на число: она заменяет многократное сложение. Например,
s = "Уа! Уа! Уа! Уа! Уа! Уа! Уа! Уа! Уа! Уа! "можно заменить на
s = "Уа! "*10или
s = 10*"Уа! "В Python каждый символ строки имеет свой номер (индекс), причём нумерация, как и во многих других языках программирования (C++, Java), всегда начинается с нуля.
Индекс можно понимать как смещение символа от начала строки. Первый по счёту символ имеет нулевое смещение (находится в самом начале строки), поэтому у него индекс 0:

К любому символу можно обратиться по индексу, записав индекс в квадратных скобках после имени строки:
print( hello[1] ) # р
print( hello[5]+hello[2]+"к" ) # тик
В языке Python можно указывать отрицательные индексы. Это значит, что отсчёт ведётся от конца строки, так что символ hello [-1] — это последний символ строки hello:

Чтобы рассчитать «нормальную» позицию символа в строке, к отрицательному индексу нужно добавить длину строки. Например:
hello[-1] = hello[len (hello)-1] = hello[6]Предыдущую программу можно было переписать, используя отрицательные индексы:
print ( hello [-6] ) # р
print ( hello[-2]+hello[-5]+"к" ) # тик
Если указать неправильный индекс, произойдёт ошибка — выход за границы строки, и программа завершится аварийно. Для строки длиной семь правильные индексы — от -7 до 6.
Поскольку к символу можно обращаться по индексу, для перебора всех символов можно использовать цикл по переменной, которая будет принимать все возможные значения индексов.
Пусть нужно вывести в столбик коды всех символов строки с именем s. Её длину можно найти с помощью функции len, индекс первого символа равен 0, а индекс последнего равен len(s)-1. Таким образом, все допустимые индексы — это последовательность, которую строит вызов функции range (len (s) ). Перебор можно выполнить так:
for i in range(len (s)) :
print ( s[i], ord(s[i]) )
В каждой строке сначала выводится сам символ, а потом — его код, который возвращает встроенная функция ord.
В языке Python существует ещё один удобный способ перебора всех элементов строки:
for с in s:
print ( с, ord(c) )
Заголовок такого цикла можно «прочитать» так: «для всех с, входящих в состав s». Это означает, что все символы строки s, с первого до последнего, по очереди оказываются в переменной с, и в теле цикла нам остаётся вывести код символа с.
В отличие от большинства современных языков программирования, в Python нельзя изменить символьную строку, поскольку строка — это неизменяемый объект. Это значит, что оператор присваивания s[5]=»a» не сработает — будет выдано сообщение об ошибке.
Тем не менее можно составить из символов существующей строки новую строку и внести в неё нужные изменения. Приведём полную программу, которая вводит строку с клавиатуры, заменяет в ней все буквы «э» на буквы «е» и выводит полученную строку на экран.
s = input ( "Введите строку: " )
sNew = ""
for с in s:
if с == "э":
с = "е"
sNew += с
print ( sNew )
Здесь в цикле for перебираются все символы, входящие в строку s. В теле цикла проверяем значение переменной с (это очередной символ исходной строки): если оно совпадает с буквой «э», то заменяем его на букву «е» и добавляем в конец новой строки sNew с помощью оператора сложения.
Нужно отметить, что показанный здесь способ (многократное «сложение» строк) работает очень медленно. В практических задачах, где требуется замена символов, лучше использовать встроенную функцию replace, о которой пойдёт речь дальше.
Для того чтобы выделить часть строки (подстроку), в языке Python применяется операция получения среза (англ, slicing). Например, s [ 3:8 ] означает «символы строки s с 3-го по 7-й» (то есть до 8-го, не включая его). Следующий фрагмент копирует в строку sMiddle символы строки s с 3-го по 7-й (всего 5 символов):
s = "0123456789"
sMiddle = s[3:8] # sMiddle = "34567"
Можно использовать и отрицательные индексы — в этом случае отсчёт идёт с конца строки:
sMiddle = s[-7:-2] # sMiddle = "34567"Для получения «нормальной» позиции символа в строке к отрицательному значению добавляется длина строки. Например, второй индекс «-2» можно заменить на len (sMiddle) -2. Это означает, что последние два символа не входят в срез.
Если первый индекс не указан, считается, что он равен нулю (берём начало строки), а если не указан второй индекс, то в срез включаются все символы до конца строки. Например:
s = "0123456789"
sFirst = s[:4] # sFirst = "0123"
sLast = s[-4:] # sLast = "6789"
Срезы позволяют легко выполнить реверс строки (развернуть её наоборот):
sReversed = s[::-l]Так как начальный и конечный индексы элементов строки не указаны, задействована вся строка. Число -1 означает шаг изменения индекса и говорит о том, что все символы перебираются в обратном порядке.
Для удаления части строки нужно составить новую строку, объединив части исходной строки до и после удаляемого участка:
s = "0123456789"
sEnds = s[:3] + s[9:] # sEnd = "0129"
Срез s[:3] означает «от начала строки до символа s[3], не включая его», а запись s[9:] — «все символы, начиная с s[9] до конца строки». Таким образом, в переменной sEnds остаётся значение «0129«.
С помощью срезов и сцепления строк можно также вставить новый фрагмент внутрь строки:
s = "0123456789"
sABC = s[:3]+" ABC " + s[3:] # sABC = "012 АВС 3456789"
В Python существует метод для поиска подстроки (и отдельного символа) в символьной строке, он называется find (по-английски — найти). В скобках нужно указать образец для поиска, это может быть один символ или символьная строка:
s = "Здесь был Вася."
n = s.find( "с" ) # n = 3
if п >= 0:
print( "Номер символа", n )
else:
print ( "Символ не найден." )
Метод find возвращает целое число — индекс символа, с которого начинается образец (буква «с») в строке s. Если образец в строке встречается несколько раз, функция находит первый из них. В рассмотренном примере в переменную n будет записано число 3. Если образец не найден, функция возвращает -1.
Аналогичный метод rfind (от англ, reverse find — искать в обратную сторону) ищет последнее вхождение образца в строку. Для той же строки s, что и в предыдущем примере, метод rfind вернёт 12 (индекс последней буквы «с»):
s = "Здесь был Вася."
n = s.rfind( "с" ) # n = 12
Иногда символьная строка, которая передаётся программе, содержит запись числа. С таким значением нельзя выполнять арифметические операции, потому что это символы, а не число.
В языке Python есть встроенные функции для преобразования типов данных, некоторые из них мы уже использовали:
int — переводит строку в целое число;
float — переводит строку в вещественное число;
str — переводит целое или вещественное число в строку.
Приведём пример преобразования строк в числовые значения:
s = "123"
n = int ( s ) # n = 123
s = "123.456"
х = float ( s ) # x = 123.456
Если строку не удаётся преобразовать в число (например, если в ней содержатся буквы), возникает ошибка и выполнение программы завершается аварийно.
Теперь покажем примеры обратного преобразования:
n=123
s=str(n) # s="123"
x=123.456
s=str(x) # s="123.456"
Эти операции всегда выполняются успешно (ошибка произойти не может).
Функция str использует правила форматирования, установленные по умолчанию. При необходимости можно использовать собственное форматирование, например:
n = 123
s = "{:5}".format( n ) # s = " 123"
Здесь значение переменной п записано в 5 позициях, т. е. в начале строки будут стоять два пробела.
Для вещественных чисел можно использовать форматы f (с фиксированной запятой) и е (научный формат, с плавающей запятой):
х = 123.456
s = "{:7.2f}".format( х ) # s = " 123.46"
s = "{:10.2е}".format( х ) # s = " 1.23е+02"
Формат 7.2f обозначает «вывести в 7 позициях с двумя знаками в дробной части», а формат 10.2е — «вывести в научном формате в 10 позициях с двумя знаками в дробной части».