Встроенный модуль string: эффективные инструменты обработки текста
Основные возможности модуля string
Как получить набор всех букв латинского алфавита (строчных и прописных) для проверки или генерации данных?
Модуль string содержит готовые строковые константы, которые можно использовать без ручного перечисления символов. Основные константы: ascii_lowercase, ascii_uppercase, ascii_letters (объединяет оба набора), digits, hexdigits, octdigits, punctuation, whitespace, printable.
import string
# Пример получения всех строчных букв
lower = string.ascii_lowercase
print(lower) # abcdefghijklmnopqrstuvwxyz
функции string python (функции строкового модуля в python)
Это позволяет быстро проверить, входит ли символ в определённую категорию, или сгенерировать случайную строку заданного набора.
Типичная ошибка
Новички часто пытаются вручную писать списки символов, что ведёт к опечаткам и дублированию кода. Использование string.ascii_letters гарантирует точность и простоту поддержки.
Как безопасно подставлять значения в строку с помощью шаблонов, избегая инъекций?
Класс string.Template предоставляет простой механизм шаблонизации с использованием $ и фигурных скобок. Он менее мощный, чем f-строки, но позволяет избежать выполнения произвольного кода при подстановке пользовательских данных.
from string import Template
t = Template('Здравствуйте, $name! Ваш заказ №$order')
message = t.substitute(name='Анна', order=1234)
print(message) # Здравствуйте, Анна! Ваш заказ №1234
Метод substitute выбрасывает KeyError, если переменная не найдена. Метод safe_substitute оставляет заполнитель нетронутым, что удобно при частичном заполнении.
Распространённая проблема
Если в строке встречается символ доллара, его нужно экранировать как $$. Иначе Template воспримет его как начало переменной.
t = Template('Цена: $$ $price')
print(t.substitute(price=199)) # Цена: $ 199
Как использовать класс Formatter для продвинутого форматирования строк с произвольными спецификациями?
Класс string.Formatter позволяет переопределить логику форматирования (например, воспринимать свои типы или менять способ подстановки). В большинстве случаев используют встроенную функцию format() или f-строки, но Formatter даёт полный контроль.
from string import Formatter
class MyFormatter(Formatter):
def format_field(self, value, format_spec):
if format_spec == 'up':
return str(value).upper()
return super().format_field(value, format_spec)
fmt = MyFormatter()
result = fmt.format('{0:up} {1}', 'hello', 'world')
print(result) # HELLO world
Это полезно для создания узкоспециализированных шаблонов, например, для автоматической локализации или трансформации данных.
Ошибки переопределения
Если не вызвать super().format_field() для неподдерживаемых спецификаций, стандартные типы (целые числа, даты) перестают работать. Рекомендуется всегда передавать управление родительскому классу для неизвестных форматов.
Как преобразовать строку в вид «Заглавные Буквы Каждого Слова» с учётом небуквенных символов?
Функция string.capwords (доступна в Python 3.x) делает заглавной первую букву каждого слова, разделённого пробелами. Она использует str.split() и str.capitalize(), что отличается от str.title(), потому что title() может неверно обработать апострофы или числа.
import string
print(string.capwords('hello world! this is a test'))
# Hello World! This Is A Test
Нюанс работы
capwords не учитывает небуквенные разделители, кроме пробелов, и всегда приводит к str.capitalize, который делает строчными все остальные буквы слова. Если нужно сохранить регистр внутри слова (например, «iPhone»), лучше использовать собственное решение.
Расширенные примеры использования модуля string
1. Генерация случайного пароля с гарантированным включением символов разных категорий
import string
import random
def generate_password(length=12):
# Определяем обязательные категории
all_chars = string.ascii_letters + string.digits + string.punctuation
# Гарантируем хотя бы один символ каждого типа
password = [
random.choice(string.ascii_lowercase),
random.choice(string.ascii_uppercase),
random.choice(string.digits),
random.choice(string.punctuation)
]
# Заполняем остаток случайными символами из всех категорий
password += random.choices(all_chars, k=length - 4)
# Перемешиваем, чтобы обязательные символы не стояли в начале
random.shuffle(password)
return ''.join(password)
print(generate_password(16))
Пример вывода: 'Yk8$fL3#zQ1!pW5x'
2. Проверка, состоит ли строка только из буквенно-цифровых символов (без знаков препинания)
import string
def is_alphanumeric_plus(s):
# Разрешены буквы, цифры, подчёркивания, но не пунктуация из string.punctuation
allowed = set(string.ascii_letters + string.digits + '_')
# Проверяем, что каждый символ входит в allowed
return all(ch in allowed for ch in s)
print(is_alphanumeric_plus('user_123')) # True
print(is_alphanumeric_plus('hello!')) # False
3. Использование Template с отображением отсутствующих ключей через safe_substitute
from string import Template
text = Template('$name имеет $count яблок')
# Пользователь не указал count - используем safe_substitute
partial = text.safe_substitute(name='Иван')
print(partial) # Иван имеет $count яблок
# Полная подстановка
full = text.substitute(name='Мария', count=5)
print(full) # Мария имеет 5 яблок
4. Извлечение всех уникальных символов пунктуации из текста
import string
def get_punctuation_chars(text):
return sorted({ch for ch in text if ch in string.punctuation})
sample = 'Привет! Как дела? (всё хорошо) - да.'
puncts = get_punctuation_chars(sample)
print(puncts) # ['!', ' ', '(', ')', '-', '.', '?']
Заметьте: string.punctuation включает пробел? Нет, пробел входит в string.whitespace, а не в punctuation. В выводе пробел появился, потому что в sample есть пробел, но он не входит в string.punctuation. Ошибка в логике функции: проверка 'ch in string.punctuation' не включает пробел, поэтому он не должен появляться. Исправленная версия:ПримерРезультат будет ['!', '(', ')', '-', '.', '?']def get_punctuation_chars(text): return sorted({ch for ch in text if ch in string.punctuation})
5. Создание собственного алфавита для шифра Цезаря с использованием констант модуля string
import string
def caesar_cipher(text, shift, alphabet=string.ascii_lowercase):
result = []
for ch in text:
if ch in alphabet:
idx = (alphabet.index(ch) + shift) % len(alphabet)
result.append(alphabet[idx])
else:
result.append(ch) # символы не из алфавита не меняем
return ''.join(result)
original = 'hello world'
shifted = caesar_cipher(original, 3)
print(shifted) # khoor zruog
# Можно использовать string.ascii_uppercase для заглавных
upper_shift = caesar_cipher('HELLO', 5, string.ascii_uppercase)
print(upper_shift) # MJQQT