PythonPython 4. Строки0%
Python для ЕГЭ · тема 4 из 11

Строки

Индексы, срезы, перебор букв, count, replace, split и маски. Строки нужны в каждом третьем номере, и даже числа на ЕГЭ часто удобнее превратить в строку.

8 разделов~45 минут№5, 8, 12, 14, 24, 25
  1. 1Индексы
  2. 2Срезы
  3. 3Перебор строки
  4. 4count, replace, in
  5. 5split и join
  6. 6Маски: fnmatch
  7. 7Сломай код
  8. 8Где пригодится на ЕГЭ
Раздел 1 из 8

Индексы

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

python
s = 'ПИТОН'
print(s[0])      # первая буква
print(s[1])      # вторая
print(len(s))    # длина строки
print(s[len(s) - 1])   # последняя

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

python
s = 'ПИТОН'
print(s[-1])     # последняя
print(s[-2])     # предпоследняя
БукваПИТОН
индекс01234
с конца−5−4−3−2−1
Раздел 2 из 8

Срезы

Срез вырезает из строки кусок: s[a:b] берёт символы с индекса a до b, не включая b. Это то же правило, что у range.

python
s = 'ИНФОРМАТИКА'
print(s[0:4])    # с 0 по 3
print(s[:4])     # то же самое: начало можно не писать
print(s[7:])     # с 7 до конца
print(s[-3:])    # последние три символа

Третье число в срезе это шаг, как в range. Шаг −1 идёт с конца, то есть переворачивает строку:

python
s = 'ИНФОРМАТИКА'
print(s[::2])    # каждая вторая буква
print(s[::-1])   # строка задом наперёд

Переворот нужен очень часто, например, чтобы проверить палиндром: строку, которая читается одинаково в обе стороны.

python
s = input()
if s == s[::-1]:
    print('палиндром')
else:
    print('не палиндром')
Ввод
Попробуй самучебная задача

Сколько чисел от 1 до 9999 являются палиндромами? Например, 7, 44, 121 и 3003.

Раздел 3 из 8

Перебор строки

for умеет перебирать не только range, но и строку: переменная по очереди становится каждой буквой.

python
k = 0
for c in 'ИНФОРМАТИКА':
    if c in 'АЕИОУЫЭЮЯ':     # c гласная?
        k += 1
print('Гласных:', k)

Когда нужно смотреть на соседние символы, перебирают не буквы, а индексы. Тогда текущая буква это s[i], а следующая s[i + 1]:

python
s = 'АББВВВГ'
k = 0
for i in range(len(s) - 1):    # до предпоследней, иначе s[i + 1] выйдет за край
    if s[i] == s[i + 1]:
        k += 1
print('Пар одинаковых соседей:', k)

Почему range(len(s) - 1)? У последней буквы соседа справа нет. Если дойти до неё, s[i + 1] выйдет за конец строки, и будет ошибка.

Самая длинная цепочка

Это основа №24. Идём по строке и держим длину текущей цепочки: если буква такая же, как предыдущая, цепочка растёт, иначе начинается заново.

python
s = 'АББВВВГВВ'
cur = 1        # длина текущей цепочки
best = 1       # самая длинная, что видели
for i in range(1, len(s)):
    if s[i] == s[i - 1]:
        cur += 1
    else:
        cur = 1
    best = max(best, cur)
print(best)
Раздел 4 из 8

count, replace, in

Три инструмента, без которых не обходится №8 и №12.

ЗаписьЧто делает
s.count('А')сколько раз встречается
'АБ' in sесть ли такой кусок в строке
s.replace('А', 'Б')новая строка, где все А заменены на Б
s.replace('А', 'Б', 1)то же, но заменить только первое А
s.upper(), s.lower()все буквы большие или маленькие
python
s = 'Мама мыла раму'
print(s.count('а'))
print('мыла' in s)
print(s.replace('а', 'о'))
print(s.lower().count('м'))    # М и м одним счётом
Строку нельзя изменить

s.replace(...) не меняет s, а возвращает новую строку. Чтобы замена сохранилась, пиши s = s.replace(...). Так же нельзя поменять одну букву через s[0] = 'Х', будет ошибка.

Замены в цикле

Задача №12 устроена так: пока в строке есть какой-то кусок, заменяем его. Это while и replace с единицей в конце, чтобы менять по одному куску за шаг:

python
s = '1' * 10                    # строка из десяти единиц
while '11' in s:
    s = s.replace('11', '2', 1)   # первое вхождение 11 меняем на 2
print(s)
Попробуй самучебная задача

Строка из 95 единиц. Пока в ней есть 22 или 111: если есть 22, первое такое заменяем на 1, иначе первое 111 заменяем на 2. Чему равна сумма цифр получившейся строки?

Раздел 5 из 8

split и join

split режет строку на части. Без аргумента режет по пробелам, а с аргументом по любому символу:

python
print('12 7 30 5'.split())
print('192.168.0.1'.split('.'))

Получается список строк. Списки подробно будут в теме 6, пока достаточно знать, что по ним можно пройти циклом:

python
s = 0
for x in '12 7 30 5'.split():
    s += int(x)          # каждый кусок это строка, превращаем в число
print(s)

join делает обратное: склеивает части в одну строку. Перед точкой пишут, чем склеивать:

python
parts = ['192', '168', '0', '1']
print('.'.join(parts))
print(''.join(parts))

''.join с пустыми кавычками ты уже видел в уроке №8: им склеивают буквы, которые выдаёт product.

Попробуй самучебная задача

Чему равна сумма чисел больше 10 в строке '12 7 30 5 18'?

Раздел 6 из 8

Маски: fnmatch

В №25 бывают условия вида «число соответствует маске 12*4?5». В маске два особых символа:

Писать такую проверку руками сложно, но в Python она уже есть: функция fnmatch из модуля с тем же названием. Число превращаем в строку и проверяем:

python
from fnmatch import fnmatch

print(fnmatch('1234', '12*4'))     # * это '3'
print(fnmatch('124', '12*4'))      # * пустая, тоже подходит
print(fnmatch('12345', '12*4'))    # в конце 5, а не 4
print(fnmatch('1294', '12?4'))     # ? это одна цифра

Пример: найдём все числа до 10 000, которые подходят под маску 1?2*5 и делятся на 25.

python
from fnmatch import fnmatch

for n in range(25, 10000, 25):       # сразу перебираем только кратные 25
    if fnmatch(str(n), '1?2*5'):
        print(n)

Обрати внимание на range с шагом 25. Нам нужны только числа, кратные 25, так что перебираем только их. Это в 25 раз быстрее, чем проверять каждое число через n % 25 == 0.

Попробуй самучебная задача

Сколько чисел меньше 1 000 000 соответствуют маске 12*4 и делятся на 19?

Раздел 7 из 8

Сломай код

IndexError: за краем строки

python
s = 'КОТ'
print(s[3])

string index out of range: в строке из 3 букв индексы 0, 1, 2. Индекса 3 нет. Чаще всего это случается при проверке соседей s[i + 1] на последней букве.

TypeError: строку не поменять

python
s = 'КОТ'
s[0] = 'Р'

'str' object does not support item assignment. Строку нельзя изменить по кусочку. Можно собрать новую: s = 'Р' + s[1:].

Тихая ошибка: replace без присваивания

python
s = 'АААБ'
s.replace('А', 'Б')
print(s)

Ничего не поменялось: новая строка получилась, но никуда не сохранилась. Нужно s = s.replace('А', 'Б').

Тихая ошибка: count не видит наложений

python
print('ААА'.count('АА'))

Кажется, что пар две (первая со второй, вторая с третьей), а count насчитал одну. Он считает вхождения, которые не накладываются друг на друга. Если наложения важны, перебирай индексы и проверяй s[i:i + 2] == 'АА'.

Раздел 8 из 8

Где пригодится на ЕГЭ

НомерЧто из темы
№8count, in, replace, проверки букв по индексу
№12while ... in s и replace(..., 1)
№24перебор строки, самая длинная цепочка, соседи
№25fnmatch для масок
№5двоичная запись это строка: срезы, count('1'), приписать цифру через +
№14подсчёт цифр в записи числа через count

В №5 это выглядит так: двоичную запись числа (о ней в следующей теме) обрабатываем как обычную строку.

python
n = 13
b = bin(n)[2:]          # двоичная запись: '1101'
if b.count('1') % 2 == 0:
    b = b + '0'
else:
    b = b + '1'
print(b, int(b, 2))     # новая запись и её значение

Тут срез [2:], count и склейка +, всё из этой темы.

Код в блоках можно менять и запускать прямо в браузере.