Python & AI Tutorials Logo
Программирование Python

5. Работа с текстом с помощью строк

Текст встречается повсюду в программировании. От вывода сообщений пользователю и обработки файлов данных до создания веб‑приложений — работа с текстом является одним из самых фундаментальных навыков, которые вы разовьёте как программист. В Python мы работаем с текстом, используя строки (strings) — последовательности символов, которые могут представлять слова, предложения или любые текстовые данные.

Вы уже встречались со строками в предыдущих главах при использовании print() и input(). Теперь мы подробно изучим строки, научимся их создавать, изменять и использовать мощные встроенные возможности Python для решения реальных задач по обработке текста.

В этой главе вы узнаете, как создавать строки со специальными символами, объединять строки, извлекать отдельные части строк, менять регистр и форматирование, искать текст внутри строк и поймёте, почему строки ведут себя иначе, чем числа, когда речь идёт об их изменении. К концу главы у вас будет твёрдая база для работы с текстом в Python.

5.1) Строковые литералы и управляющие последовательности

5.1.1) Создание строковых литералов

Строковый литерал (string literal) — это строковое значение, записанное непосредственно в вашем коде. Вы уже видели строки, создаваемые с помощью одинарных (') или двойных (") кавычек:

python
# string_basics.py
greeting = 'Hello, World!'
message = "Python is great!"
 
print(greeting)  # Output: Hello, World!
print(message)   # Output: Python is great!

Одинарные и двойные кавычки в Python работают идентично — выбор за вами. Однако наличие обоих вариантов удобно, когда сама строка содержит символы кавычек:

python
# quotes_in_strings.py
# Используем двойные кавычки, когда строка содержит одинарную кавычку
sentence = "It's a beautiful day!"
print(sentence)  # Output: It's a beautiful day!
 
# Используем одинарные кавычки, когда строка содержит двойные кавычки
quote = 'She said, "Hello!"'
print(quote)  # Output: She said, "Hello!"

Если вам нужно включить в строку тот же тип кавычек, которым она окружена, вы можете экранировать его с помощью обратной косой черты (\):

python
# escaping_quotes.py
# Экранирование одинарной кавычки внутри строки в одинарных кавычках
sentence = 'It\'s a beautiful day!'
print(sentence)  # Output: It's a beautiful day!
 
# Экранирование двойных кавычек внутри строки в двойных кавычках
quote = "She said, \"Hello!\""
print(quote)  # Output: She said, "Hello!"

Обратная косая черта говорит Python, что следующая кавычка является частью содержимого строки, а не концом строки.

5.1.2) Многострочные строки с тройными кавычками

Для строк, которые занимают несколько строк, Python предоставляет тройные кавычки — либо три одинарные ('''), либо три двойные (""") кавычки:

python
# multiline_strings.py
poem = """Roses are red,
Violets are blue,
Python is awesome,
And so are you!"""
 
print(poem)
# Output:
# Roses are red,
# Violets are blue,
# Python is awesome,
# And so are you!

Строки в тройных кавычках сохраняют все переводы строк и пробелы ровно в том виде, как вы их набрали. Они особенно полезны для длинных текстовых блоков, строк документации (мы увидим их в главе 19) или когда вам нужно включить и одинарные, и двойные кавычки без экранирования:

python
# triple_quotes_convenience.py
dialogue = '''The teacher said, "Don't forget: it's important to practice!"'''
print(dialogue)  # Output: The teacher said, "Don't forget: it's important to practice!"

5.1.3) Распространённые управляющие последовательности

Помимо экранирования кавычек, обратная косая черта вводит управляющие последовательности (escape sequences) — специальные двухсимвольные комбинации, представляющие символы, которые сложно или невозможно ввести напрямую:

python
# escape_sequences.py
# Newline: переход на следующую строку
print("First line\nSecond line")
# Output:
# First line
# Second line
 
# Tab: вставка горизонтального отступа
print("Name:\tJohn\nAge:\t25")
# Output:
# Name:	John
# Age:	25
 
# Backslash: чтобы включить буквальный обратный слеш
path = "C:\\Users\\Documents"
print(path)  # Output: C:\Users\Documents

Вот наиболее часто используемые управляющие последовательности:

Escape SequenceMeaningExample Output
\nNewline (line break)Two lines
\tTab (horizontal spacing)Indented text
\\Backslash\ character
\'Single quote' character
\"Double quote" character

Понимание управляющих последовательностей крайне важно при работе с путями к файлам (особенно в Windows, где используются обратные слеши), форматированным выводом или любым текстом, требующим специального форматирования.

5.1.4) Необработанные строки (raw strings) для буквальных обратных слешей

Иногда вы хотите, чтобы обратные слеши интерпретировались буквально, без запуска управляющих последовательностей. Это часто бывает при работе с путями к файлам или регулярными выражениями (кратко затронем их в главе 39). Python предоставляет необработанные строки (raw strings), которые создаются с префиксом r:

python
# raw_strings.py
# Обычная строка: обратные слеши запускают управляющие последовательности
regular = "C:\new\test"
print(regular)  # Output: C:
                #         ew   est
                # (\n становится переходом строки, \t становится табуляцией)
 
# Необработанная строка: обратные слеши трактуются буквально
raw = r"C:\new\test"
print(raw)  # Output: C:\new\test

В необработанной строке \n — это буквально два символа: обратная косая черта и n, а не перевод строки. Необработанные строки особенно полезны для путей Windows:

python
# windows_paths.py
# Без необработанной строки нужно экранировать каждый обратный слеш
path1 = "C:\\Users\\John\\Documents\\file.txt"
 
# С необработанной строкой обратные слеши работают естественным образом
path2 = r"C:\Users\John\Documents\file.txt"
 
print(path1)  # Output: C:\Users\John\Documents\file.txt
print(path2)  # Output: C:\Users\John\Documents\file.txt

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

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

5.2.1) Конкатенация строк с помощью +

Вы можете объединять строки, используя оператор +, который называется конкатенацией (concatenation):

python
# string_concatenation.py
first_name = "John"
last_name = "Smith"
 
# Объединение строк с помощью +
full_name = first_name + " " + last_name
print(full_name)  # Output: John Smith
 
# Построение более длинных строк
greeting = "Hello, " + full_name + "!"
print(greeting)  # Output: Hello, John Smith!

Конкатенация создаёт новую строку, помещая строки одну за другой. Обратите внимание, что Python не добавляет пробелы автоматически — их нужно включать явно:

python
# concatenation_spacing.py
word1 = "Hello"
word2 = "World"
 
# Без пробела
no_space = word1 + word2
print(no_space)  # Output: HelloWorld
 
# С пробелом
with_space = word1 + " " + word2
print(with_space)  # Output: Hello World

Вы можете конкатенировать сколько угодно строк в одном выражении:

python
# multiple_concatenation.py
address = "123" + " " + "Main" + " " + "Street"
print(address)  # Output: 123 Main Street

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

python
# concatenation_error.py
age = 25
# Это вызовет ошибку:
# message = "I am " + age + " years old"  # TypeError!
 
# Сначала нужно преобразовать число в строку
message = "I am " + str(age) + " years old"
print(message)  # Output: I am 25 years old

Мы подробнее рассмотрим преобразование строк и чисел в разделе 5.6.

5.2.2) Повторение строк с помощью *

Python предоставляет удобный способ повторять строку несколько раз с помощью оператора *:

python
# string_repetition.py
separator = "-" * 20
print(separator)  # Output: --------------------
 
# Создание шаблонов
pattern = "abc" * 3
print(pattern)  # Output: abcabcabc
 
# Полезно для форматирования вывода
print("=" * 30)
print("Important Message")
print("=" * 30)
# Output:
# ==============================
# Important Message
# ==============================

Оператор повторения работает с любым положительным целым числом:

python
# repetition_examples.py
# Повторение ноль раз даёт пустую строку
nothing = "Hello" * 0
print(nothing)      # Output: (empty string)
print(len(nothing)) # Output: 0
 
# Повторение один раз даёт исходную строку
once = "Hello" * 1
print(once)  # Output: Hello
 
# Большие повторы
many = "Go! " * 5
print(many)  # Output: Go! Go! Go! Go! Go!

Повторение строк особенно полезно для создания визуальных разделителей, заполнения (padding) или генерации тестовых данных:

python
# practical_repetition.py
# Создание простого текстового блока
width = 40
border = "=" * width
title = "Welcome"
padding = " " * ((width - len(title)) // 2)
 
print(border)
print(padding + title)
print(border)
# Output:
# ========================================
#                 Welcome
# ========================================

5.2.3) Комбинирование конкатенации и повторения

Вы можете комбинировать оба оператора в одном выражении, следуя правилам приоритета операторов в Python (умножение перед сложением, как и с числами):

python
# combined_operations.py
# Сначала выполняется повторение, затем конкатенация
result = "=" * 10 + " Title " + "=" * 10
print(result)  # Output: ========== Title ==========
 
# Использование скобок для управления порядком
repeated_phrase = ("Hello " + "World ") * 3
print(repeated_phrase)  # Output: Hello World Hello World Hello World

Эти операции составляют основу манипуляций со строками, позволяя строить сложные строки из простых частей.

5.3) Индексация и срезы строк

Строки в Python — это последовательности (sequences) символов, а значит, каждый символ имеет определённую позицию. Вы можете получать доступ к отдельным символам или извлекать части строки с помощью индексации и срезов.

5.3.1) Понимание индексов строки

Каждый символ в строке имеет числовую позицию, называемую индексом (index). Python использует индексацию с нуля (zero-based indexing), то есть первый символ имеет индекс 0, второй — 1 и так далее:

python
# string_indexing.py
text = "Python"
 
# Доступ к отдельным символам по индексу
print(text[0])  # Output: P (first character)
print(text[1])  # Output: y (second character)
print(text[5])  # Output: n (sixth character)

Наглядное отображение соответствия индексов и символов:

String:  P  y  t  h  o  n
Index:   0  1  2  3  4  5

Python также поддерживает отрицательные индексы (negative indices), которые отсчитываются с конца строки. Индекс -1 обозначает последний символ, -2 — предпоследний и так далее:

python
# negative_indexing.py
text = "Python"
 
print(text[-1])  # Output: n (last character)
print(text[-2])  # Output: o (second-to-last)
print(text[-6])  # Output: P (first character)

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

String:    P  y  t  h  o  n
Positive:  0  1  2  3  4  5
Negative: -6 -5 -4 -3 -2 -1

String: 'Python'

Положительная индексация

Отрицательная индексация

[0] = 'P'
[1] = 'y'
[2] = 't'
[3] = 'h'
[4] = 'o'
[5] = 'n'

[-6] = 'P'
[-5] = 'y'
[-4] = 't'
[-3] = 'h'
[-2] = 'o'
[-1] = 'n'

Важно: попытка обратиться к индексу, который не существует, вызовет IndexError:

python
# index_error.py
text = "Python"
 
# Это работает нормально
print(text[5])  # Output: n
 
# Это вызовет ошибку, потому что индекса 6 не существует
# print(text[6])  # IndexError: string index out of range

5.3.2) Срезы строк для извлечения подстрок

Индексация даёт вам один символ, а срезы (slicing) позволяют извлечь часть строки (называемую подстрокой (substring)). Базовый синтаксис:

string[start:stop]

Это извлекает символы с индекса start до (но не включая) индекс stop:

python
# basic_slicing.py
text = "Python Programming"
 
# Извлечь символы с индекса 0 до (но не включая) 6
print(text[0:6])  # Output: Python
 
# Извлечь символы с индекса 7 до 18
print(text[7:18])  # Output: Programming
 
# Извлечь среднюю часть
print(text[7:11])  # Output: Prog

Ключевой момент: индекс stop не включается в результат. Представьте, что индексы указывают на позиции между символами:

 P  y  t  h  o  n
 0  1  2  3  4  5  6

Тогда text[0:6] означает «начать в позиции 0 и остановиться перед позицией 6», что даёт символы с позиций 0, 1, 2, 3, 4 и 5.

5.3.3) Пропуск начального или конечного индекса

Вы можете опустить индекс start, чтобы срез начинался с начала строки, или опустить индекс stop, чтобы срез шёл до конца:

python
# omitting_indices.py
text = "Python Programming"
 
# От начала до индекса 6
print(text[:6])  # Output: Python
 
# От индекса 7 до конца
print(text[7:])  # Output: Programming
 
# Вся строка (от начала до конца)
print(text[:])  # Output: Python Programming

Эти сокращения очень распространены в Python‑коде, так как они ясно выражают намерения и позволяют избежать жёсткого указания длин.

5.3.4) Использование отрицательных индексов в срезах

Отрицательные индексы работают и в срезах, позволяя отсчитывать с конца:

python
# negative_slice_indices.py
text = "Python Programming"
 
# Последние 11 символов
print(text[-11:])  # Output: Programming
 
# Всё, кроме последних 11 символов
print(text[:-11])  # Output: Python
 
# Последние 7 символов
print(text[-7:])  # Output: ramming
 
# От индекса 7 до третьего с конца символа
print(text[7:-3])  # Output: Programm (останавливается перед 'ing')

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

python
# removing_suffix.py
filename = "document.txt"
 
# Взять всё, кроме последних 4 символов (.txt)
name_without_extension = filename[:-4]
print(name_without_extension)  # Output: document

5.3.5) Срезы с шагом

Срезы могут включать третье значение — шаг (step), которое определяет, сколько символов пропускать:

string[start:stop:step]
python
# slicing_with_step.py
text = "Python Programming"
 
# Каждый второй символ из всей строки
print(text[::2])  # Output: Pto rgamn
 
# Каждый второй символ с индекса 0 до 6
print(text[0:6:2])  # Output: Pto
 
# Каждый третий символ
print(text[::3])  # Output: Ph oai

Особо полезный приём — использование шага -1 для разворота строки:

python
# reversing_strings.py
text = "Python"
 
# Развернуть всю строку
reversed_text = text[::-1]
print(reversed_text)  # Output: nohtyP
 
# Практический пример: проверка палиндромов
word = "radar"
if word == word[::-1]:
    print(f"{word} is a palindrome!")  # Output: radar is a palindrome!

5.3.6) Срезы никогда не вызывают ошибок

В отличие от индексации, срезы очень «прощают ошибки». Если вы укажете индексы вне диапазона, Python просто подгонит их под существующие границы:

python
# safe_slicing.py
text = "Python"
 
# Всё это работает без ошибок
print(text[0:100])   # Output: Python (останавливается в конце)
print(text[10:20])   # Output: (empty string - start is beyond end)
print(text[-100:3])  # Output: Pyt (start скорректирован до 0)

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

5.3.7) Практические примеры срезов

Вот несколько распространённых шаблонов, которые вы будете часто использовать:

python
# practical_slicing.py
text = "Hello, World!"
 
# Первые 5 символов
print(text[:5])  # Output: Hello
 
# Последние 6 символов
print(text[-6:])  # Output: World!
 
# Всё, кроме первого и последнего символа
print(text[1:-1])  # Output: ello, World
 
# Каждый второй символ
print(text[::2])  # Output: Hlo ol!
 
# Разворот строки
print(text[::-1])  # Output: !dlroW ,olleH

Понимание индексации и срезов фундаментально для обработки текста в Python. Эти приёмы будут неоднократно встречаться на всём вашем пути в программировании.

5.4) Распространённые строковые методы для регистра и пробельных символов

Строки в Python имеют множество встроенных методов (methods) — функций, «прикреплённых» к объектам строк и выполняющих над ними операции. В этом разделе мы рассмотрим методы для изменения регистра и управления пробельными символами, которые необходимы для очистки и форматирования текста.

5.4.1) Понимание строковых методов

Метод (method) вызывается с использованием точечной нотации: string.method_name(). Методы — это функции, принадлежащие объекту определённого типа. Для строк Python предоставляет десятки полезных методов:

python
# method_basics.py
text = "hello"
 
# Вызов метода у строки
result = text.upper()
print(result)  # Output: HELLO
 
# Исходная строка не изменяется (почему — обсудим в разделе 5.8)
print(text)  # Output: hello

Методы можно вызывать цепочкой, потому что каждый метод возвращает новую строку:

python
# method_chaining.py
text = "  hello world  "
 
# Цепочка из нескольких методов
result = text.strip().upper().replace("WORLD", "PYTHON")
print(result)  # Output: HELLO PYTHON

5.4.2) Методы изменения регистра

Python предоставляет несколько методов для изменения регистра строк:

python
# case_methods.py
text = "Python Programming"
 
# Преобразовать в верхний регистр
print(text.upper())  # Output: PYTHON PROGRAMMING
 
# Преобразовать в нижний регистр
print(text.lower())  # Output: python programming
 
# Сделать первую букву заглавной, остальные — строчными
print(text.capitalize())  # Output: Python programming
 
# Title case: сделать первую букву каждого слова заглавной
print(text.title())  # Output: Python Programming

Эти методы особенно полезны для стандартизации пользовательского ввода:

python
# case_normalization.py
# Имитация пользовательского ввода
user_input = "YES"
 
# Сравнение без учёта регистра
if user_input.lower() == "yes":
    print("User confirmed!")  # Output: User confirmed!
 
# Другой подход с использованием upper()
command = "start"
if command.upper() == "START":
    print("Starting process...")  # Output: Starting process...

Метод title() делает заглавной первую букву каждого слова, что полезно для форматирования имён и заголовков:

python
# title_case.py
name = "john smith"
print(name.title())  # Output: John Smith
 
book = "the great gatsby"
print(book.title())  # Output: The Great Gatsby

Однако у title() есть ограничения с апострофами и особыми случаями:

python
# title_limitations.py
text = "it's a beautiful day"
print(text.title())  # Output: It'S A Beautiful Day (обратите внимание на заглавную S)
 
# Для более сложного форматирования заголовков может понадобиться своя логика

Метод capitalize() делает заглавной только самый первый символ всей строки:

python
# capitalize_examples.py
sentence = "python is great"
print(sentence.capitalize())  # Output: Python is great
 
# Обратите внимание: только первая буква становится заглавной
multi_word = "hello world"
print(multi_word.capitalize())  # Output: Hello world (не Hello World)

5.4.3) Методы проверки регистра

Python также предоставляет методы для проверки регистра строк:

python
# case_checking.py
text1 = "HELLO"
text2 = "hello"
text3 = "Hello World"
 
# Проверить, все ли символы в верхнем регистре
print(text1.isupper())  # Output: True
print(text2.isupper())  # Output: False
 
# Проверить, все ли символы в нижнем регистре
print(text1.islower())  # Output: False
print(text2.islower())  # Output: True
 
# Проверить, находится ли строка в формате title case
print(text3.istitle())  # Output: True
print(text2.istitle())  # Output: False

Эти методы возвращают True или False (логические значения, о которых мы говорили в главе 3), что делает их идеальными для условий:

python
# case_checking_conditions.py
password = "SECRET123"
 
if password.isupper():
    print("Password is all uppercase")  # Output: Password is all uppercase

5.4.4) Методы удаления пробельных символов

Пробельные символы (whitespace) включают пробелы, табуляции (\t) и переводы строк (\n). Python предоставляет методы для удаления пробельных символов по краям строк:

python
# whitespace_removal.py
text = "   Hello, World!   "
 
# Удалить пробельные символы с обоих концов
print(text.strip())  # Output: Hello, World!
 
# Удалить пробельные символы слева (в начале)
print(text.lstrip())  # Output: Hello, World!   
 
# Удалить пробельные символы справа (в конце)
print(text.rstrip())  # Output:    Hello, World!

Метод strip() чрезвычайно полезен для очистки пользовательского ввода:

python
# cleaning_input.py
# Имитация пользовательского ввода с лишними пробелами
user_name = "  John Smith  "
 
# Очистка ввода
clean_name = user_name.strip()
print(f"Welcome, {clean_name}!")  # Output: Welcome, John Smith!

Эти методы также удаляют табуляции и переводы строк:

python
# strip_all_whitespace.py
text = "\n\t  Hello  \t\n"
print(repr(text))  # Output: '\n\t  Hello  \t\n'
 
cleaned = text.strip()
print(repr(cleaned))  # Output: 'Hello'

Обратите внимание, что strip(), lstrip() и rstrip() удаляют пробельные символы только по краям, но не в середине строки:

python
# strip_edges_only.py
text = "  Hello   World  "
print(text.strip())  # Output: Hello   World (пробелы в середине остаются)

5.4.5) Удаление конкретных символов

Методы strip также могут удалять конкретные символы (не только пробельные) с краёв строки:

python
# Удаление нескольких разных символов
text = "...Hello!!!"
cleaned = text.strip(".!")
print(cleaned)  # Output: Hello

Когда вы передаёте строку в strip(), он удаляет любую комбинацию этих символов с обоих концов:

python
# strip_character_set.py
text = "xxxyyyHelloyyyxxx"
 
# Удалить любые символы x или y с обоих концов
result = text.strip("xy")
print(result)  # Output: Hello

5.4.6) Практические примеры комбинирования методов регистра и пробелов

Вот реальные сценарии, в которых эти методы незаменимы:

python
# practical_text_cleaning.py
# Очистка и стандартизация пользовательского ввода
user_email = "  JohnSmith@EXAMPLE.com  "
clean_email = user_email.strip().lower()
print(clean_email)  # Output: johnsmith@example.com
 
# Корректное форматирование имён
raw_name = "  john smith  "
formatted_name = raw_name.strip().title()
print(formatted_name)  # Output: John Smith
 
# Обработка команд (без учёта регистра)
command = "  START  "
if command.strip().upper() == "START":
    print("Command recognized!")  # Output: Command recognized!

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

5.5) Поиск и замена в строках

Поиск и модификация текста внутри строк — распространённая задача в программировании. Python предоставляет мощные методы для поиска подстрок и замены текста.

5.5.1) Поиск подстрок с помощью find() и index()

Метод find() ищет подстроку и возвращает индекс, где она впервые встречается:

python
# find_method.py
text = "Python is great. Python is powerful."
 
# Найти первое вхождение "Python"
position = text.find("Python")
print(position)  # Output: 0 (found at the beginning)
 
# Найти "great"
position = text.find("great")
print(position)  # Output: 10
 
# Найти то, чего нет
position = text.find("Java")
print(position)  # Output: -1 (not found)

Метод find() возвращает -1, если подстрока не найдена, что делает его безопасным — он не вызывает ошибок:

python
# safe_searching.py
text = "Hello, World!"
 
# Проверить, существует ли подстрока
if text.find("World") != -1:
    print("Found 'World'!")  # Output: Found 'World'!
 
if text.find("Python") == -1:
    print("'Python' not found")  # Output: 'Python' not found

Вы также можете искать подстроку, начиная с определённой позиции:

python
# find_with_start.py
text = "Python is great. Python is powerful."
 
# Найти первое вхождение
first = text.find("Python")
print(first)  # Output: 0
 
# Найти следующее вхождение после первого
second = text.find("Python", first + 1)
print(second)  # Output: 17

Метод index() работает похоже на find(), но вызывает ошибку, если подстрока не найдена:

python
# index_method.py
text = "Hello, World!"
 
# Это работает нормально
position = text.index("World")
print(position)  # Output: 7
 
# Это вызовет ValueError:
# position = text.index("Python")  # ValueError: substring not found

Когда что использовать:

  • Используйте find(), когда вы хотите проверить, существует ли подстрока (возвращает -1, если не найдена)
  • Используйте index(), если вы уверены, что подстрока должна быть (вызывает ошибку, если не найдена)
python
# choosing_find_vs_index.py
text = "Python Programming"
 
# Использование find() для безопасной проверки
if text.find("Java") != -1:
    print("Found Java")
else:
    print("Java not found")  # Output: Java not found
 
# Использование index(), когда вы уверены, что подстрока есть
position = text.index("Python")  # Мы знаем, что Python там есть
print(f"Found at position {position}")  # Output: Found at position 0

5.5.2) Поиск с конца с помощью rfind() и rindex()

Методы rfind() и rindex() ищут, начиная справа (с конца) строки:

python
# rfind_method.py
text = "Python is great. Python is powerful."
 
# Найти последнее вхождение "Python"
last_position = text.rfind("Python")
print(last_position)  # Output: 17
 
# Сравнить с find(), который даёт первое вхождение
first_position = text.find("Python")
print(first_position)  # Output: 0

Это полезно, когда вам нужно последнее вхождение чего‑либо:

python
# last_occurrence.py
filename = "document.backup.txt"
 
# Найти последнюю точку (чтобы получить расширение файла)
last_dot = filename.rfind(".")
if last_dot != -1:
    extension = filename[last_dot:]
    print(extension)  # Output: .txt

5.5.3) Подсчёт вхождений с помощью count()

Метод count() показывает, сколько раз подстрока встречается в строке:

python
# count_method.py
text = "Python is great. Python is powerful. Python is fun."
 
# Посчитать, сколько раз встречается "Python"
count = text.count("Python")
print(count)  # Output: 3
 
# Посчитать букву
letter_count = text.count("o")
print(f"Letter 'o' appears {letter_count} times")  # Output: Letter 'o' appears 4 times

Можно также считать вхождения в определённом диапазоне:

python
# count_in_range.py
text = "abcabcabc"
 
# Посчитать "abc" во всей строке
total = text.count("abc")
print(total)  # Output: 3
 
# Посчитать "abc" только в первых 6 символах
partial = text.count("abc", 0, 6)
print(partial)  # Output: 2

5.5.4) Замена текста с помощью replace()

Метод replace() создаёт новую строку, в которой все вхождения подстроки заменены:

python
# replace_method.py
text = "I love Java. Java is great."
 
# Заменить все вхождения "Java" на "Python"
new_text = text.replace("Java", "Python")
print(new_text)  # Output: I love Python. Python is great.
 
# Исходная строка не изменяется
print(text)  # Output: I love Java. Java is great.

Вы можете ограничить количество замен третьим аргументом:

python
# limited_replace.py
text = "one one one one"
 
# Заменить только первые 2 вхождения
result = text.replace("one", "two", 2)
print(result)  # Output: two two one one

Метод replace() чувствителен к регистру:

python
# case_sensitive_replace.py
text = "Python is great. python is powerful."
 
# Это заменит только "Python" (с заглавной P)
result = text.replace("Python", "Java")
print(result)  # Output: Java is great. python is powerful.

Для замены без учёта регистра нужно обрабатывать это вручную:

python
# case_insensitive_approach.py
text = "Python is great. python is powerful."
 
# Преобразовать в нижний регистр, заменить, но при этом теряется исходный регистр
result = text.lower().replace("python", "java")
print(result)  # Output: java is great. java is powerful.

5.5.5) Практические примеры поиска и замены

Вот реальные сценарии, где эти методы особенно полезны:

python
# practical_search_replace.py
# Очистка данных: удаление лишних символов
phone = "123-456-7890"
clean_phone = phone.replace("-", "")
print(clean_phone)  # Output: 1234567890
 
# Цензура слов
message = "This is a bad word and another bad word."
censored = message.replace("bad", "***")
print(censored)  # Output: This is a *** word and another *** word.
 
# Извлечение расширения файла
filename = "document.txt"
dot_position = filename.rfind(".")
if dot_position != -1:
    extension = filename[dot_position + 1:]
    print(f"File type: {extension}")  # Output: File type: txt
 
# Подсчёт вхождений слова (простой подход)
text = "Python is fun. I love Python. Python rocks!"
word = "Python"
occurrences = text.count(word)
print(f"'{word}' appears {occurrences} times")  # Output: 'Python' appears 3 times

find

rfind

count

replace

String: 'Hello World Hello'

Операция поиска

find('Hello')
Возвращает: 0

rfind('Hello')
Возвращает: 12

count('Hello')
Возвращает: 2

replace('Hello', 'Hi')
Возвращает: 'Hi World Hi'

Первое вхождение
слева

Последнее вхождение
справа

Общее количество
вхождений

Новая строка
с заменами

Эти методы поиска и замены являются базовыми инструментами для обработки текста, очистки данных и манипуляций со строками в программах на Python.

5.6) Преобразование между строками и числами

Одна из самых распространённых задач в программировании — преобразование между текстовыми и числовыми представлениями. Когда вы читаете пользовательский ввод с помощью input(), вы получаете строку, даже если пользователь ввёл число. Точно так же, когда вы хотите отобразить числа в тексте, нужно преобразовать их в строки.

5.6.1) Преобразование строк в числа

Мы уже видели функции int() и float() в главе 3, но давайте рассмотрим их подробнее:

python
# string_to_number.py
# Преобразование строки в целое число
age_text = "25"
age = int(age_text)
print(age)        # Output: 25
print(type(age))  # Output: <class 'int'>
 
# Преобразование строки в число с плавающей точкой
price_text = "19.99"
price = float(price_text)
print(price)        # Output: 19.99
print(type(price))  # Output: <class 'float'>

Эти преобразования необходимы при обработке пользовательского ввода:

python
# user_input_conversion.py
# Имитация пользовательского ввода (в реальном коде вы бы использовали input())
user_age = "30"
user_height = "5.9"
 
# Преобразуем в числа, чтобы можно было выполнять вычисления
age = int(user_age)
height = float(user_height)
 
# Теперь можно выполнять вычисления
print(f"In 10 years, you'll be {age + 10}")  # Output: In 10 years, you'll be 40
print(f"Your height in meters: {height * 0.3048:.2f}")  # Output: Your height in meters: 1.80

Важно: строка должна представлять собой корректное число, иначе вы получите ошибку:

python
# conversion_errors.py
# Эти варианты работают нормально
print(int("123"))      # Output: 123
print(float("3.14"))   # Output: 3.14
 
# Эти вызовут ValueError:
# print(int("hello"))     # ValueError: invalid literal for int()
# print(int("12.5"))      # ValueError: invalid literal for int() with base 10
# print(float("12.5.3"))  # ValueError: could not convert string to float

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

5.6.2) Обработка пробелов в числовых строках

Функции преобразования Python автоматически обрабатывают начальные и конечные пробелы:

python
# whitespace_handling.py
# Все эти варианты работают несмотря на пробелы
print(int("  42  "))      # Output: 42
print(float("  3.14  "))  # Output: 3.14
 
# Комбинирование strip() с преобразованием для надёжности
user_input = "  100  "
number = int(user_input.strip())
print(number)  # Output: 100

Это помогает при обработке пользовательского ввода, где часто встречаются лишние пробелы.

5.6.3) Преобразование чисел в строки

Функция str() преобразует любое значение в его строковое представление:

python
# number_to_string.py
age = 25
height = 5.9
 
# Преобразовать числа в строки
age_text = str(age)
height_text = str(height)
 
print(type(age_text))     # Output: <class 'str'>
print(type(height_text))  # Output: <class 'str'>
 
# Теперь можно конкатенировать их с другими строками
message = "I am " + str(age) + " years old"
print(message)  # Output: I am 25 years old

Это необходимо каждый раз, когда вы хотите объединять числа со строками:

python
# concatenation_with_numbers.py
score = 95
total = 100
 
# Для конкатенации нужно преобразовать числа в строки
result = "Score: " + str(score) + "/" + str(total)
print(result)  # Output: Score: 95/100
 
# Альтернатива: использовать f-строки (подробно в главе 6)
result = f"Score: {score}/{total}"
print(result)  # Output: Score: 95/100

5.6.4) Преобразование между int и float

Вы также можете преобразовывать значения между типами int и float:

python
# int_float_conversion.py
# Float в int (отсекает дробную часть)
price = 19.99
price_int = int(price)
print(price_int)  # Output: 19 (дробная часть удалена, не округлено)
 
# Int в float
age = 25
age_float = float(age)
print(age_float)  # Output: 25.0

Важно: преобразование float в int отсекает (обрезает) дробную часть — оно не округляет:

python
# truncation_not_rounding.py
print(int(3.9))   # Output: 3 (не 4!)
print(int(3.1))   # Output: 3
print(int(-3.9))  # Output: -3 (обрезает к нулю)
 
# Чтобы округлить, используйте сначала функцию round() (обсуждается в главе 4)
print(int(round(3.9)))  # Output: 4

5.6.5) Практические примеры преобразований

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

python
# practical_conversions.py
# Чтение и обработка пользовательского ввода
# (Имитация input() — в реальном коде вы бы использовали input())
user_input = "42"
 
# Преобразовать в число, чтобы выполнять вычисления
number = int(user_input)
doubled = number * 2
print(f"Double of {number} is {doubled}")  # Output: Double of 42 is 84
 
# Построение форматированного вывода
name = "John"
age = 30
height = 5.9
 
# Метод 1: преобразовать числа в строки
info = name + " is " + str(age) + " years old and " + str(height) + " feet tall"
print(info)  # Output: John is 30 years old and 5.9 feet tall
 
# Метод 2: использовать f-строки (нагляднее — см. главу 6)
info = f"{name} is {age} years old and {height} feet tall"
print(info)  # Output: John is 30 years old and 5.9 feet tall
 
# Обработка данных из файлов (предварительный пример)
data_line = "100,200,300"  # Имитация строки из CSV‑файла
numbers = data_line.split(",")  # Разбить на список строк
total = int(numbers[0]) + int(numbers[1]) + int(numbers[2])
print(f"Total: {total}")  # Output: Total: 600

5.6.6) Типичные подводные камни при преобразовании

Обратите внимание на следующие распространённые ошибки:

python
# conversion_pitfalls.py
# Подводный камень 1: попытка преобразовать нечисловые строки
# text = "hello"
# number = int(text)  # ValueError!
 
# Подводный камень 2: забыли преобразовать перед арифметикой
age_text = "25"
# next_year = age_text + 1  # TypeError: can only concatenate str to str
 
# Правильный подход:
age = int(age_text)
next_year = age + 1
print(next_year)  # Output: 26
 
# Подводный камень 3: потеря точности при int()
price = 19.99
price_int = int(price)  # Становится 19, а не 20!
print(price_int)  # Output: 19
 
# Подводный камень 4: попытка преобразовать строки с запятыми или символами валют
# price_text = "$1,234.56"
# price = float(price_text)  # ValueError!
 
# Сначала нужно очистить строку:
price_text = "$1,234.56"
clean_price = price_text.replace("$", "").replace(",", "")
price = float(clean_price)
print(price)  # Output: 1234.56

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

5.7) Проверка подстрок с помощью in и not in

Python предоставляет простые и наглядные способы проверить, содержит ли одна строка другую, с помощью операторов in и not in. Они чрезвычайно полезны для валидации, фильтрации и принятия решений в ваших программах.

5.7.1) Использование in для проверки подстрок

Оператор in возвращает True, если одна строка содержится в другой, и False в противном случае:

python
# in_operator.py
text = "Python is a powerful programming language"
 
# Проверить, существует ли подстрока
print("Python" in text)      # Output: True
print("powerful" in text)    # Output: True
print("Java" in text)        # Output: False

Это гораздо более читаемо, чем использование find() или index():

python
# in_vs_find.py
text = "Hello, World!"
 
# Использование in (наглядно и понятно)
if "World" in text:
    print("Found World!")  # Output: Found World!
 
# Использование find (менее наглядно)
if text.find("World") != -1:
    print("Found World!")  # Output: Found World!

Оператор in чувствителен к регистру:

python
# case_sensitivity.py
text = "Python Programming"
 
print("python" in text)   # Output: False (строчная 'p')
print("Python" in text)   # Output: True (заглавная 'P')
 
# Для проверки без учёта регистра сначала переводим в нижний регистр
print("python" in text.lower())  # Output: True

5.7.2) Использование not in для проверки отсутствия

Оператор not in проверяет, что подстрока отсутствует:

python
# not_in_operator.py
text = "Python is great"
 
print("Java" not in text)     # Output: True (Java там нет)
print("Python" not in text)   # Output: False (Python там есть)

Это особенно полезно для валидации:

python
# validation_examples.py
# Проверка недопустимых символов в имени пользователя
username = "john_smith"
 
if " " not in username:
    print("Username is valid (no spaces)")  # Output: Username is valid (no spaces)

5.7.3) Дополнительные методы проверки строк

Python предоставляет и другие полезные методы проверки свойств строк:

python
# string_checking_methods.py
text = "Python"
 
# Проверить, начинается ли строка с подстроки
print(text.startswith("Py"))   # Output: True
print(text.startswith("Ja"))   # Output: False
 
# Проверить, заканчивается ли строка подстрокой
print(text.endswith("on"))     # Output: True
print(text.endswith("ing"))    # Output: False
 
# Эти методы точнее, чем использование in
filename = "report.txt"
print(filename.endswith(".txt"))  # Output: True
print(".txt" in filename)         # Output: True (но менее точно)
 
# startswith/endswith могут проверять несколько вариантов
filename = "document.pdf"
print(filename.endswith((".pdf", ".doc", ".txt")))  # Output: True

Эти методы проверки являются важными инструментами для валидации ввода, фильтрации данных и условной логики в программах. Они делают ваш код более читаемым и поддерживаемым по сравнению с ручным поиском по строкам.

5.8) Строки неизменяемы: что это значит на практике

Одна из важнейших характеристик строк в Python — они неизменяемы (immutable): после создания их нельзя изменить. Это может показаться ограничением, но понимание неизменяемости критически важно для написания корректного кода на Python и избежания тонких ошибок.

5.8.1) Что означает неизменяемость

Когда мы говорим, что строки неизменяемы, мы имеем в виду, что вы не можете изменить символы в уже существующей строке. Любая операция, которая как будто «изменяет» строку, на самом деле создаёт новую строку:

python
# immutability_basics.py
text = "Hello"
 
# Кажется, что строка изменяется, но это не так
text = text + " World"
print(text)  # Output: Hello World
 
# Что на самом деле произошло:
# 1. Python создал новую строку "Hello World"
# 2. Переменная 'text' теперь ссылается на эту новую строку
# 3. Исходная строка "Hello" всё ещё существует (пока не будет удалена сборщиком мусора)

Вы не можете изменить отдельные символы в строке:

python
# cannot_modify_characters.py
text = "Hello"
 
# Это вызовет ошибку:
# text[0] = "J"  # TypeError: 'str' object does not support item assignment
 
# Вместо этого нужно создать новую строку
text = "J" + text[1:]
print(text)  # Output: Jello

Это принципиально отличается от работы со списками (lists), о которых мы узнаем в главе 13. Списки изменяемы — вы можете менять их элементы:

python
# lists_are_mutable.py
# Предварительный пример списков (подробно в главе 13)
numbers = [1, 2, 3]
numbers[0] = 10  # Для списков это вполне допустимо
print(numbers)   # Output: [10, 2, 3]
 
# Но строки такого не позволяют:
text = "Hello"
# text[0] = "J"  # TypeError для строк!

5.8.2) Почему строковые методы возвращают новые строки

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

python
# methods_return_new_strings.py
original = "hello world"
 
# Эти методы возвращают новые строки
uppercase = original.upper()
capitalized = original.capitalize()
replaced = original.replace("world", "Python")
 
# Исходная строка не изменилась
print(original)      # Output: hello world
print(uppercase)     # Output: HELLO WORLD
print(capitalized)   # Output: Hello world
print(replaced)      # Output: hello Python

Поэтому, чтобы сохранить изменения, нужно присвоить результат переменной (или той же самой переменной):

python
# keeping_changes.py
text = "  hello  "
 
# Неверно: результат теряется
text.strip()
print(text)  # Output:   hello   (пробелы всё ещё на месте!)
 
# Верно: присвоить результат
text = text.strip()
print(text)  # Output: hello (пробелы убраны)

Это распространённая ошибка новичков:

python
# common_mistake.py
message = "python programming"
 
# Ошибка: вызов метода без использования результата
message.upper()
message.replace("python", "Python")
print(message)  # Output: python programming (без изменений!)
 
# Правильно: присваивать результаты
message = message.upper()
message = message.replace("PYTHON", "Python")
print(message)  # Output: Python PROGRAMMING

5.8.3) Последствия неизменяемости

Понимание неизменяемости помогает писать более надёжный код:

1. Строки безопасно «делить» между частями кода:

python
# safe_sharing.py
original = "Hello"
copy = original  # Обе переменные ссылаются на одну и ту же строку
 
# Поскольку строки неизменяемы, это безопасно
copy = copy + " World"
 
print(original)  # Output: Hello (без изменений)
print(copy)      # Output: Hello World (новая строка)

2. Операции со строками создают новые объекты:

python
# new_objects.py
text = "Python"
 
# Каждая операция создаёт новый объект строки
result1 = text.upper()
result2 = text.lower()
result3 = text.replace("P", "J")
 
# Все это разные объекты
print(id(text))     # Некоторый адрес в памяти
print(id(result1))  # Другой адрес
print(id(result2))  # Другой адрес
print(id(result3))  # Другой адрес

3. Построение строк в циклах может быть неэффективным:

python
# inefficient_string_building.py
# Здесь создаётся много временных объектов строк
result = ""
for i in range(5):
    result = result + str(i)  # Каждый раз создаётся новая строка
print(result)  # Output: 01234
 
# Более эффективный подход (для большого числа конкатенаций):
# Использовать список и join (об этом мы узнаем в главе 6)
parts = []
for i in range(5):
    parts.append(str(i))
result = "".join(parts)
print(result)  # Output: 01234

5.8.4) Неизменяемость и аргументы функций

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

python
# safe_function_arguments.py
def process_text(text):
    # Любые операции создают новые строки
    text = text.upper()
    text = text.replace("A", "X")
    return text
 
original = "banana"
result = process_text(original)
 
print(original)  # Output: banana (без изменений)
print(result)    # Output: BXNXNX (изменённая версия)

Это отличается от изменяемых типов (например, списков, о которых мы поговорим в главе 13), где изменения внутри функции затрагивают исходный объект.

5.8.5) Визуализация неизменяемости

Вот наглядное представление того, что происходит, когда вы «изменяете» строку:

text = 'Hello'

Память: 'Hello' по адресу 1000

text = text + ' World'

Что происходит?

1. Создаётся новая строка 'Hello World' по адресу 2000
2. Переменная 'text' теперь указывает на адрес 2000
3. Исходная 'Hello' по адресу 1000 остаётся
до удаления сборщиком мусора

text теперь ссылается на 'Hello World'

Понимание того, что строки неизменяемы, помогает вам:

  1. Избегать ошибок, когда вы забываете сохранить результат методов
  2. Понимать, почему операции со строками создают новые объекты
  3. Писать более эффективный код при построении больших строк
  4. Безопасно использовать строки в разных частях программы

Неизменяемость — фундаментальная характеристика, отличающая строки от изменяемых типов, таких как списки, которые мы подробно изучим в части IV этой книги.


Итоги главы:

В этой главе вы познакомились с основами работы с текстом в Python с помощью строк. Теперь вы умеете:

  • Создавать строковые литералы с использованием кавычек и управляющих последовательностей
  • Объединять строки с помощью конкатенации и повторять строки с помощью оператора *
  • Получать отдельные символы и извлекать подстроки с помощью индексации и срезов
  • Преобразовывать строки с помощью методов изменения регистра и удаления пробельных символов
  • Искать и заменять текст внутри строк
  • Преобразовывать строки и числа для обработки ввода и форматирования вывода
  • Проверять наличие подстрок с помощью операторов in и not in
  • Понимать, что строки неизменяемы, и учитывать это в своём коде

Эти навыки работы со строками составляют основу обработки текста в Python. Вы будете постоянно использовать эти приёмы при создании пользовательских интерфейсов, обработке файлов данных, проверке ввода и форматировании вывода.

В следующей главе мы расширим эти основы, изучив более продвинутые приёмы работы со строками, включая разбиение и объединение строк, мощное форматирование с помощью f‑строк и метода format(), а также основы кодировок текста для работы с международными символами.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai