06. Строки. Форматирование.


Методы строк

Мы уже знаем что-то про строки (впрочем, основное, что нужно о них знать) - как брать срезы (подпоследовательности) строк, как их складывать, как узнать длину строки, два полезных метода join и split.

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

Библиотека `string`

Это очень небольшая библиотека, но она может быть полезна, чтобы иметь "группы" символов под рукой, а не создавать их самим (однако, там далеко не все символы, например, там нет букв не английского алфавита). Таким образом можно получить все пунктуационные и пробельный символы:

In [ ]:
import string
string.punctuation, string.digits, string.whitespace

Метод `find`

Это метод поиска подстроки в строке, как легко понять из названия. Он возвращает индекс (только неотрицательный) первого вхождения подстроки в строку, а если она не нашлась то -1.

In [ ]:
s = 'python string'
s.find('o'), s.find('str'), s.find('P')
In [ ]:
s.find('t')

Как видим t было найдено только одно - в слове python. В методе есть позиционные параметры в каком интервале искать подстроку. То есть метод выглядит в "общем" виде так:

Строка.find(ИскомаяПодстрока, Старт, Конец)

In [ ]:
s = 'python string'
s.find('t', 0, 5), s.find('t', -5, -2), s.find('t', s.find('t') + 1), s.find('th', 5)

Метод `rfind`

Он работает аналогично find, но ищет самое правое вхождение (первое с конца).

In [ ]:
s = 'python to do'
s.rfind('n to')
In [ ]:
s.rfind('t', 9, 100)
In [ ]:
s = ' ' + 'a' * 100000
In [ ]:
%timeit s.rfind(' ')
In [ ]:
%timeit s[::-1].find(' ')

Метод `replace`

Имеет три позиционных параметра - old, new и необязательный count. Возвращает строку, в которой все вхождения или, если указано, count первых вхождений подстроки old заменены на подстроку new.

In [ ]:
s = 'Python 3 Python 3'
s_new = s.replace('P', 'C')
In [ ]:
s_new2 = s_new.replace('3', ';)')
print(s, s_new, s_new2, sep=' -> ')
In [ ]:
s = 'AAAAAAAA' # 8 букв А
s_new = s.replace('AA', 'A')
s_new2 = s.replace('AA', 'A', 2)
print(s, s_new, s_new2)

Метод `count`

Выдает целое число - количество непересекающихся вхождений подстроки. По аналогии с методом find есть параметры интервала поиска.

In [ ]:
s = 'python python 3'
s.count(' python ') # обратите внимание на пробел
In [ ]:
s = 'AAAAAAAA' # 8 букв А
s.count('A'), s.count('AA', 3, 7), s.count('AAA', 3, 7), s[3:7] 
# обратитет внимание, что вхождения подстрок НЕ ПЕРЕСЕКАЮТСЯ!

Другие методы

Методы, проверяющие состав строки

S.isdigit() Состоит ли строка ТОЛЬКО из цифр

In [ ]:
'123'.isdigit(), '1a'.isdigit(), '1,2,3'.isdigit(), '1 2 3'.isdigit(),\
''.isdigit(), ' '.isdigit()

S.isalpha() Состоит ли строка только из букв

In [ ]:
'абвσ'.isalpha(), 'a1b2b3'.isalpha(), 'a,b,c'.isalpha(), \
'a b c'.isalpha(), ''.isalpha(), ' '.isalpha()

S.isalnum() Состоит ли строка из цифр или букв

In [ ]:
'a'.isalnum(), '1'.isalnum(), 'a1'.isalnum(), \
'a,1'.isalnum(), 'a 1'.isalnum(), ''.isalnum(), ' '.isalnum()

S.islower() Состоит ли строка только из символов в нижнем регистре

In [ ]:
's'.islower(), 's,s'.islower(), ','.islower(), '1'.islower(),\
'S'.islower(), ''.islower(), ' '.islower()

S.isupper() Состоит ли строка только из символов в верхнем регистре

In [ ]:
'S'.isupper(), 'S,S'.isupper(), ','.isupper(), '1'.isupper(),\
's'.isupper(), ''.isupper(), ' '.isupper()

S.istitle() Начинаются ли все слова (слова := идущие подряд буквы (=символы имеющие регистр) без разделения "небуквой" (=символ не имеющий регистр)) в строке с заглавной буквы

In [ ]:
'Python 3 Python'.istitle(), 'Python3Python'.istitle(), 'A'.istitle(), '!P'.istitle(), \
'Python1python'.istitle(), 'python 3'.istitle(), '3py'.istitle(), ''.istitle(), ' '.istitle()

S.startswith(str, start=0, end=-1) Начинается ли строка S[start:end] со строки str.

In [ ]:
myfiles = ['forloop.png', 'lecture01_intro.ipynb', 'lecture01_intro_slides.ipynb', 
           'lecture02_if.ipynb', 'lecture02_if_slides.ipynb', 'lecture03_container.ipynb', 
           'lecture03_container_slides.ipynb', 'lecture04_for.ipynb', 'lecture04_for_slides.ipynb', 
           'lecture05_def.ipynb',  'lecture05_def_slides.ipynb', 'lecture06_str_slides.ipynb', 
           'qrcode.png']

for file in myfiles:
    print(file.startswith('lecture'), end=', ')

S.endswith(str) Заканчивается ли строка S строкой str

In [ ]:
for file in myfiles:
    print(file.endswith('.png'), end=', ')
In [ ]:
for file in myfiles:
    print(file.split('.')[0].endswith('slides'), end=', ')

Методы, работающие с регистром символов

S.capitalize() Переводит первый символ строки в верхний регистр, а все остальные в нижний

In [ ]:
s, S = 'the StOry oF My life1', 'SALE 100%'
s.capitalize(), S.capitalize()

S.swapcase() Переводит символы нижнего регистра в верхний, а верхнего – в нижний

In [ ]:
s.swapcase(), S.swapcase()

S.title() Первую букву каждого слова переводит в верхний регистр, а все остальные в нижний

In [ ]:
s.title(), S.title()

S.upper() Преобразование строки к верхнему регистру

In [ ]:
s.upper()

S.lower() Преобразование строки к нижнему регистру

In [ ]:
S.lower()

Функции для работы с кодом Unicode

ord(символ) Возвращает код символа

In [ ]:
ord('A'), ord('a'), ord('&')

chr(число) Возвращает символ по его коду

In [ ]:
chr(42), chr(57), chr(69), chr(100)

Форматирование строк Подробнее

Бывает нам хочется напечатать что-то вроде такого:

In [ ]:
n, m = int(input()), int(input())

print('Number of students\nGroup 1:', n, '\nGroup 2:', m, '\nOverall:', n + m)

Проблема: приходится "изменяемые" переменные вставлять через запятые, остальной строковой текст все время обрамлять в кавычки. Конечно, приведенный пример это далеко на самый плохой вариант, н опредставьте, если таких переменных, например, 100? Уже сложнее. Питонисты любят когда все коротко и ясно. Поэтому есть такой метод (впрочем, не только), .format(). Работает он следующим образом:

In [ ]:
s = 'Это число {}, это буква "{}", это предложение "{}"'
s.format(n, m, n+m)
In [ ]:
s = 'Это число {2}, это буква "{1}", это предложение "{0}"'
s.format(1, 'a', 'Hi, Monty!!')
In [ ]:
s = 'Это число {x[2]}, это буква "{x[1]}", это предложение "{x[0]}"'
p = (1, 'a', 'Hi, Monty!!')
s.format(x=p)

То есть Питон считывает строку, видит в ней "фигурные скобки" - места куда вставить объекты, и то, что лежит внутри метода .format() вставляет в том порядке, в котором они указаны (по дефолту подряд), создавая новый объект типа строка.

Также можно указать сколько чисел после запятой вывести у вещественного числа:

In [ ]:
pi = 3.14159265559
print('Number pi = {:.5f}'.format(pi), 
      'Number pi = {:.0f}'.format(pi),
      'Number pi = {: 6.2f}'.format(pi), sep='\n')

Можно "паддить" строки:

In [ ]:
print('|{:>10}|\n|{:^10}|\n|{:<10}|\n|{:.^10}|'.format('Hello', 'Hi', 'Hey', 'Hi'))

Usage case:

In [ ]:
# генерируем строку, в которую хотим вставить какие-то значения
toprint = '\n'.join([chr(65 + i) + chr(97 + i) +': {: 5.0f}|' for i in range(26)])
toprint
In [ ]:
# вводим какие-то данные
tocount = input().lower()
# производим вычисления с переменными данными
counted_alphabet = [tocount.count(chr(97 + i)) for i in range(26)]
# печатаем с помощью форматирования
print(toprint.format(*counted_alphabet))

f-string

Абсолютно то же самое (в новых версиях Питона) можно делать следующим более кратким и удобным (не всегда) способом:

In [ ]:
name = 'Sonya'
yr = 2020
old = 22
f'Hi, my name is {name}. I was born in {yr-old}.'
In [ ]:
'Hi, my name is {}. I was born in {}.'.format(name, yr-old)