Строки и последовательности символов в языке Python
Строка в Python представляет собой неизменяемую последовательность символов. Это означает, что каждый элемент строки – отдельный символ (в том числе Unicode), и к нему можно обратиться по индексу, но нельзя изменить строку на месте. Строки поддерживают все операции, свойственные последовательностям: индексацию, срезы, конкатенацию, повторение, проверку вхождения.
Основные операции и их варианты
Эффективный доступ к символам и подстрокам
Базовый способ работы со строкой как с последовательностью – использовать квадратные скобки для получения отдельного символа или подстроки (срез).
s = "Python"
print(s[0]) # P
print(s[-1]) # n
print(s[1:4]) # yth
print(s[::-1])# nohtyPпоследовательность символов в python (последовательность символов в python)
Индексация начинается с нуля, отрицательные индексы отсчитывают с конца. Срез [start:stop:step] позволяет извлечь подстроку. Это самый быстрый и компактный способ работы.
Типичные ошибки:
- IndexError при обращении к несуществующему индексу – проверяйте длину строки через len(s).
- Путаница с границами среза: stop не включается. s[1:3] вернет символы с индексами 1 и 2, но не 3.
Как перебрать все символы строки один за другим?
Цикл for позволяет последовательно получить каждый символ без использования индекса.
word = "Привет"
for char in word:
print(char, end=' ')
# вывод: П р и в е т
Этот способ удобен, когда нужно выполнить действие над каждым символом, например, подсчитать количество определенных букв.
text = "Hello world"
count = 0
for c in text:
if c.lower() in 'aeiou':
count += 1
print(count) # 3
Проблемы и решения:
Строки неизменяемы, поэтому изменить символ внутри цикла напрямую не получится. Если нужно построить новую строку с изменениями, используйте список и метод join().
s = "abc"
new = [chr(ord(ch) + 1) for ch in s]
print(''.join(new)) # bcd
Как во время перебора получить не только символ, но и его индекс?
Функция enumerate() возвращает пары (индекс, символ).
word = "index"
for i, char in enumerate(word):
print(f"{i}: {char}")
# 0: i
# 1: n
# 2: d
# 3: e
# 4: x
Параметр start позволяет задать начальное значение индекса.
for i, c in enumerate("abc", start=1):
print(i, c)
# 1 a
# 2 b
# 3 c
Ошибка:
Забывают, что enumerate возвращает итератор, а не список. Если нужно использовать результат несколько раз, оберните в list().
Как получить строку в обратном порядке символов?
Срез с шагом -1 – самый простой и быстрый способ.
s = "зеркало"
reversed_s = s[::-1]
print(reversed_s) # олакрез
Другой вариант – встроенная функция reversed(), которая возвращает итератор. Чтобы получить строку, используйте ''.join().
s = "abc"
rev = ''.join(reversed(s))
print(rev) # cba
Проблема:
При использовании reversed() без join() получится итератор, а не строка. Для многократного использования лучше сохранить результат.
Как проверить, содержится ли подстрока в строке?
Оператор in и not in возвращают булево значение.
s = "Python programming"
if "thon" in s:
print("найдено")
else:
print("не найдено")
Для регистронезависимого поиска используйте lower() или метод casefold().
s = "Hello"
print("hello" in s.lower()) # True
Частая ошибка:
Путаница между in для последовательностей (проверка элемента) и in для подстрок. В строке in работает для любой подстроки.
Как эффективно объединить несколько строк в одну?
Метод join() принимает итерируемый объект и вставляет разделитель между элементами. Это гораздо эффективнее, чем многократное использование оператора +.
words = ["Python", "is", "great"]
sentence = ' '.join(words)
print(sentence) # Python is great
Если разделитель не нужен, используйте пустую строку.
chars = ['a', 'b', 'c']
result = ''.join(chars)
print(result) # abc
Ошибки:
- Попытка join() от нестроковых элементов – нужно предварительно преобразовать в строки (например, map(str, ...)).
- Использование + для конкатенации в цикле (создает много промежуточных строк) – замените на список и join().
Как разбить строку на подстроки по разделителю?
Метод split() по умолчанию делит по пробельным символам (пробел, табуляция, новая строка) и удаляет лишние.
text = "один два три"
parts = text.split()
print(parts) # ['один', 'два', 'три']
Можно указать конкретный разделитель.
csv = "a,b,c"
fields = csv.split(',')
print(fields) # ['a', 'b', 'c']
Метод partition() разбивает на три части по первому вхождению разделителя.
s = "hello-world"
head, sep, tail = s.partition('-')
print(head, tail) # hello world
Типичные проблемы:
- Если разделитель не найден, split() возвращает список из одного элемента, а partition() возвращает исходную строку и два пустых.
- Неявный split без аргумента удаляет лишние пробелы – если нужно сохранить пустые строки, используйте split(' ') с явным аргументом.
Как вставить значения переменных в строку?
Наиболее современный способ – f-строки (Python 3.6+). Они читаемы и быстры.
name = "Анна"
age = 25
greeting = f"Меня зовут {name}, мне {age} лет."
print(greeting)
Также можно использовать метод format() или оператор %.
print("Привет, {}!".format(name))
print("Возраст: %d" % age)
Проблемы:
- В f-строках фигурные скобки нужно экранировать двойными: {{ }}.
- Ошибка при использовании обратного слеша внутри фигурных скобок – нельзя писать {x\n}.
- В format() путаница с позиционными и именованными аргументами.
Расширенные примеры работы с последовательностями символов
Ниже приведены дополнительные приёмы, которые помогут глубже понять строки как последовательности и избежать подводных камней.
Unicode и сырые строки
Функции ord() и chr() позволяют работать с кодами символов. Сырые строки (r'...') отключают экранирование обратным слешем.
print(ord('A')) # 65
print(chr(65)) # A
s = "Hello\nWorld"
print(s)
# Hello
# World
raw = r"Hello\nWorld"
print(raw) # Hello\nWorld
65 A Hello World Hello\nWorld
Замена символов через translate
str.maketrans() и translate() позволяют выполнять замену множества символов за один проход.
table = str.maketrans('aeiou', '12345')
s = "hello world"
print(s.translate(table)) # h2ll4 w4rld
h2ll4 w4rld
Разбиение по нескольким разделителям
Модуль re предоставляет регулярные выражения для сложного разбиения.
import re
text = "раз;два,три:четыре"
parts = re.split(r'[;,:\s]+', text)
print(parts) # ['раз', 'два', 'три', 'четыре']
['раз', 'два', 'три', 'четыре']
Проверка типов символов
Методы isalpha, isdigit, isalnum, isspace, istitle, islower, isupper возвращают True, если все символы удовлетворяют условию.
print("123".isdigit()) # True
print("abc".isalpha()) # True
print("abc123".isalnum()) # True
print(" ".isspace()) # True
print("Hello".istitle()) # True
print("hello".islower()) # True
True True True True True True
Поиск подстроки: find vs index
find() возвращает -1, если подстрока не найдена; index() выбрасывает ValueError.
s = "python"
print(s.find('y')) # 1
print(s.find('z')) # -1
print(s.index('y')) # 1
# print(s.index('z')) # ValueError
1 -1 1
Подсчет вхождений и замена
count() считает непересекающиеся вхождения; replace() может ограничить количество замен.
s = "abracadabra"
print(s.count('a')) # 5
print(s.replace('a', 'o')) # obrocodobro
print(s.replace('a', 'o', 2)) # obrocadabra
5 obrocodobro obrocadabra
Удаление пробелов и указанных символов
strip(), lstrip(), rstrip() с аргументом удаляют любые символы из набора по краям строки.
s = " hello "
print(s.strip()) # hello
print(s.lstrip()) # hello
print(s.rstrip()) # hello
s2 = "...hello..."
print(s2.strip('.')) # hello
hello
hello
hello
hello
Выравнивание и дополнение нулями
zfill(), ljust(), rjust(), center() используются для форматирования текста.
print("42".zfill(5)) # 00042
print("hello".ljust(10)) # 'hello '
print("hello".rjust(10)) # ' hello'
print("hello".center(10)) # ' hello '
00042
hello
hello
hello
Преобразование регистра и сравнение
title(), capitalize(), swapcase(), casefold() – для изменения регистра. Сравнение строк основано на кодах Unicode.
s = "hello world"
print(s.title()) # Hello World
print(s.capitalize()) # Hello world
print(s.swapcase()) # HELLO WORLD
s2 = "Python"
print(s2.casefold() == "python") # True
print("abc" < "abd") # True
Hello World Hello world HELLO WORLD True True