Мне всегда нравились странные персонажи.
Тим Бёртон
Благодаря книгам о компьютерах может сложиться впечатление, что программирование — это чистая математика. На самом деле большинство программистов гораздо чаще работают с текстовыми строками, а не с числами. В таком случае логическое (и креативное!) мышление бывает гораздо важнее математических навыков.
Строки являются первым примером последовательностей в Python. В частности, они представляют собой последовательности символов. Но что такое символ? Это наименьшая единица письменной системы, которая может быть буквой, цифрой, специальным символом, знаком препинания и даже пробелом или директивой вроде linefeeds. Символ определяется своим значением (тем, как он используется), а не тем, как он выглядит. У него может быть более одного визуального представления (в разных шрифтах), и, в свою очередь, одинаковое представление могут иметь несколько символов (например, символ Н в латинском алфавите обозначает звук «х», а в кириллическом — «н»).
В этой главе рассматривается создание и форматирование простых текстовых строк на примере базового набора символов ASCII. Две важные темы, касающиеся текстов, обсуждаются в главе 12: символы Unicode (к этой теме относится ситуация с символом Н, о которой я только что упомянул) и регулярные выражения (сравнение с шаблоном).
В отличие от других языков в Python строки являются неизменяемыми. Вы не можете изменить саму строку, но можете скопировать части строк в другую строку, чтобы добиться подобного эффекта. Скоро вы узнаете, как это делается.
Строка в Python создается заключением символов в парные одинарные или двойные кавычки:
>>> 'Snap'
'Snap'
>>> "Crackle"
'Crackle'
Интерактивный интерпретатор выводит на экран строки в одинарных кавычках, но все они обрабатываются одинаково.
В Python существует несколько особых типов строк, определяемых буквой, стоящей перед первой кавычкой. С буквы f или F начинается f-строка, которая используется для форматирования: она описана в конце главы. С буквы r или R начинается необработанная строка — она используется для предотвращения создания управляющих символов в строке (см. раздел «Создаем escape-последовательности с помощью символа \» на с. 94 и главу 12, в которой рассказывается об их использовании при проверке на соответствие шаблону). Возможна и комбинация fr (а также FR, Fr или fR), с которой начинается необработанная f-строка. Буквой u запускается строка из символов Unicode, аналогичная простой строке. С буквы b начинается значение объекта типа bytes (см. главу 12). Если я не упоминаю один из этих особых типов, значит, речь идет о старой доброй текстовой строке, содержащей символы Unicode.
Зачем нужны два вида кавычек? Основная идея заключается в том, чтобы позволить программисту создавать строки, содержащие символы кавычек. Вы можете пользоваться одинарными кавычками внутри строк, созданных с помощью двойных кавычек, и наоборот:
>>> "'Nay,' said the naysayer. 'Neigh?' said the horse."
"'Nay,' said the naysayer. 'Neigh?' said the horse."
>>> 'The rare double quote in captivity: ".'
'The rare double quote in captivity: ".'
>>> 'A "two by four" is actually 1 1/2" × 3 1/2".'
'A "two by four is" actually 1 1/2" × 3 1/2".'
>>> "'There's the man that shot my paw!' cried the limping hound."
"'There's the man that shot my paw!' cried the limping hound."
Допускается также использование трех одинарных (''') или трех двойных кавычек ("""):
>>> '''Boom!'''
'Boom'
>>> """Eek!"""
'Eek!'
Тройные кавычки не очень подходят для таких коротких строк. Обычно они используются для того, чтобы создавать многострочный текст наподобие следующего классического стихотворения Эдварда Лира:
>>> poem = '''There was a Young Lady of Norway,
... Who casually sat in a doorway;
... When the door squeezed her flat,
... She exclaimed, "What of that?"
... This courageous Young Lady of Norway.'''
>>>
(Это стихотворение было введено в интерактивный интерпретатор, который поприветствовал нас символами >>> в первой строке и выводил приглашения … до тех пор, пока мы не ввели последние тройные кавычки и не перешли к следующей строке.)
Если вы попытаетесь создать стихотворение без тройных кавычек, Python начнет волноваться, когда вы перейдете к следующей строке:
>>> poem = 'There was a young lady of Norway,
File "<stdin>", line 1
poem = 'There was a young lady of Norway,
^
SyntaxError: EOL while scanning string literal
>>>
Если внутри тройных кавычек располагается несколько строк, символы конца строки будут сохранены в строке. Если есть начальные или конечные пробелы, они также будут сохранены:
>>> poem2 = '''I do not like thee, Doctor Fell.
... The reason why, I cannot tell.
... But this I know, and know full well:
... I do not like thee, Doctor Fell.
... '''
>>> print(poem2)
I do not like thee, Doctor Fell.
The reason why, I cannot tell.
But this I know, and know full well:
I do not like thee, Doctor Fell.
>>>
Кстати, существует разница между выводом на экран с помощью функции print() и автоматическим выводом на экран с помощью интерактивного интерпретатора:
>>> poem2
'I do not like thee, Doctor Fell.\n The reason why, I cannot tell.\n But
this I know, and know full well:\n I do not like thee, Doctor Fell.\n'
Функция print() выводит на экран содержимое строк и при этом удаляет из них кавычки. Она предназначена для удобства пользователя — услужливо добавляет пробел между каждым выводимым объектом, а также символ новой строки в конце:
>>> print ('Give', "us", '''some''', """space""")
Give us some space
Если вам не нужны пробелы или переход на новую строку, в главе 14 вы узнаете, как от них избавиться.
Интерактивный интерпретатор выводит строку с одинарными кавычками и управляющими символами, такими как \n: это объясняется в разделе «Создаем escape-последовательности с помощью символа \» далее в этой главе.
>>> """'Guten Morgen, mein Herr!'
... said mad king Ludwig to his wig."""
"'Guten Morgen, mein Herr!'\nsaid mad king Ludwig to his wig."
Наконец, вам может понадобиться поработать с пустой строкой. В ней нет символов, но она совершенно корректна. Пустая строка создается с помощью любых упомянутых ранее кавычек:
>>> ''
''
>>> ""
''
>>> ''''''
''
>>> """"""
''
>>>
Создать строку из другого типа данных можно с помощью функции str():
>>> str(98.6)
'98.6'
>>> str(1.0e4)
'10000.0'
>>> str(True)
'True'
В Python функция str() используется также для внутренних нужд: например, при вызове функции print() для объектов, которые не являются строками, и при форматировании строк, о чем мы поговорим далее в этой главе.
Python позволяет использовать escape-последовательности внутри строк, чтобы добиться эффекта, который по-другому выразить было бы трудно. Символ с размещенным перед ним обратным слешем (\) получает особое значение. Наиболее распространена последовательность \n, которая означает переход на новую строку. С ее помощью можно создавать многострочные строки из однострочных:
>>> palindrome = 'A man,\nA plan,\nA canal:\nPanama.'
>>> print(palindrome)
A man,
A plan,
A canal:
Panama.
Последовательность \t (табуляция) используется для выравнивания текста:
>>> print('\tabc')
abc
>>> print('a\tbc')
a bc
>>> print('ab\tc')
ab c
>>> print('abc\t')
abc
(В последней строке табуляция стоит в конце, но увидеть ее вы, конечно, не можете.)
Кроме того, вам могут понадобиться последовательности \' или \", чтобы поместить одинарные или двойные кавычки в строку, заключенную в такие же символы:
>>> testimony = "\"I did nothing!\" he said. \"Or that other thing.\""
>>> testimony
'"I did nothing!" he said. "Or that other thing."'
>>> print(testimony)
"I did nothing!" he said. "Or that other thing."
>>> fact = "The world's largest rubber duck was 54'2\" by 65'7\" by 105'"
>>> print(fact)
The world's largest rubber duck was 54'2" by 65'7" by 105'
А если вам нужен обратный слеш, просто напечатайте два (первый из них экранирует второй):
>>> speech = 'The backslash (\\) bends over backwards to please you.'
>>> print(speech)
The backslash (\) bends over backwards to please you.
>>>
Как я упоминал ранее в этой главе, в необработанной строке escape-символы не работают:
>>> info = r'Type a \n to get a new line in a normal string'
>>> info
'Type a \\n to get a new line in a normal string'
>>> print(info)
Type a \n to get a new line in a normal string
(Интерактивный интерпретатор добавил дополнительный обратный слеш при первом отображении значения переменной info.)
В необработанных строках работают все реальные (а не выполненные с помощью последовательности '\n') переходы на новую строку:
>>> poem = r'''Boys and girls, come out to play.
... The moon doth shine as bright as day.'''
>>> poem
'Boys and girls, come out to play.\nThe moon doth shine as bright as day.'
>>> print(poem)
Boys and girls, come out to play.
The moon doth shine as bright as day.
В Python вы можете объединить строки или строковые переменные с помощью оператора +, как показано далее:
>>> 'Release the kraken! ' + 'No, wait!'
'Release the kraken! 'No, wait!'
Строки (не переменные) можно объединять, просто расположив их одну за другой:
>>> "My word! " "A gentleman caller!"
'My word! A gentleman caller!'
>>> "Alas! ""The kraken!"
'Alas! The kraken!'
Если подобных действий много, избежать создания переходов на новую строку можно, заключив строки в скобки:
>>> vowels = ( 'a'
... "e" '''i'''
... 'o' """u"""
... )
>>> vowels
'aeiou'
Python сам не добавляет пробелы при конкатенации строк, поэтому в более ранних примерах нам нужно было явно проставлять пробелы. Python добавляет пробел между каждым аргументом выражения print() и символом новой строки в конце:
>>> a = 'Duck.'
>>> b = a
>>> c = 'Grey Duck!'
>>> a + b + c
'Duck. Duck. Grey Duck!'
>>> print(a, b, c)
Duck. Duck. Grey Duck!
Оператор * можно использовать для того, чтобы размножить строку. Попробуйте ввести в интерактивный интерпретатор следующие строки и посмотрите, что получится:
>>> start = 'Na ' * 4 + '\n'
>>> middle = 'Hey ' * 3 + '\n'
>>> end = 'Goodbye.'
>>> print(start + start + middle + end)
Обратите внимание на то, что оператор * имеет более высокий приоритет, чем +, поэтому строка будет размножена до того, как к ней добавится символ перехода на новую строку.
Для получения одного символа из строки укажите его смещение в квадратных скобках после имени строки. Смещение первого (крайнего слева) символа равно 0, следующего — 1 и т.д. Чтобы не считать, смещение последнего (крайнего справа) символа можно указать как –1. В таком случае смещение последующих символов будет равно –2, –3 и т.д.:
>>> letters = 'abcdefghijklmnopqrstuvwxyz'
>>> letters[0]
'a'
>>> letters[1]
'b'
>>> letters[-1]
'z'
>>> letters[-2]
'y'
>>> letters[25]
'z'
>>> letters[5]
'f'
Если вы укажете смещение, равное длине строки или больше (помните, смещения идут от 0 к длине –1), сгенерируется исключение:
>>> letters[100]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
Индексирование работает и для других типов последовательностей (списков и кортежей), которые я рассмотрю в главе 7.
Поскольку строки неизменяемы, вы не можете вставить символ непосредственно в строку или изменить символ по заданному индексу. Попробуем изменить слово Henny на слово Penny и посмотрим, что произойдет:
>>> name = 'Henny'
>>> name[0] = 'P'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Вместо этого вам придется использовать комбинацию строковых функций (совсем скоро вы ее увидите), таких как replace() или slice:
>>> name = 'Henny'
>>> name.replace('H', 'P')
'Penny'
>>> 'P' + name[1:]
'Penny'
Мы не изменили значение переменной name. Интерактивный интерпретатор просто вывел на экран результат замены.
Из строки можно извлечь подстроку (часть строки) с помощью разделения.
Вы задаете разделение с помощью квадратных скобок, смещения начала подстроки начало и смещения конца подстроки конец, а также опционального размера шага между ними шаг. Некоторые из этих параметров могут быть пропущены. В подстроку будут включены символы, расположенные от точки, на которую указывает смещение начало, до точки, на которую указывает смещение конец.
• Оператор [:] извлекает всю последовательность от начала до конца.
• Оператор [начало:] извлекает последовательность с точки, на которую указывает смещение начало, до конца.
• Оператор [:конец] извлекает последовательность от начала до точки, на которую указывает смещение конец минус 1.
• Оператор [начало:конец] извлекает последовательность с точки, на которую указывает смещение начало, до точки, на которую указывает смещение конец минус 1.
• Оператор [начало:конец:шаг] извлекает последовательность с точки, на которую указывает смещение начало, до точки, на которую указывает смещение конец минус 1, опуская символы, чье смещение внутри подстроки кратно шаг.
Как и ранее, смещение слева направо определяется как 0, 1 и т.д., а справа налево — как –1, –2 и т.д. Если вы не укажете смещение начало, функция будет использовать в качестве его значения 0 (начало строки). Если не укажете смещение конец, его значением будет считаться конец строки.
Создадим строку, содержащую английские буквы в нижнем регистре:
>>> letters = 'abcdefghijklmnopqrstuvwxyz'
Использование простого двоеточия аналогично использованию последовательности 0: (целая строка):
>>> letters[:]
'abcdefghijklmnopqrstuvwxyz'
Вот так можно получить все символы, начиная с 20-го и заканчивая последним:
>>> letters[20:]
'uvwxyz'
Так — начиная с 10-го и заканчивая последним:
>>> letters[10:]
'klmnopqrstuvwxyz'
А теперь получим символы с 12-го по 14-й. Python не включает в разделение конечное смещение. Стартовое смещение включено, а конечное — не включено:
>>> letters[12:15]
'mno'
Последние три символа:
>>> letters[-3:]
'xyz'
В следующем примере мы начинаем со смещения 18 и идем до четвертого с конца символа. Обратите внимание, как этот пример отличается от предыдущего, в котором старт с позиции –3 приводил к букве х. В этом примере конец диапазона –3 означает, что последней будет буква со смещением –4 — w:
>>> letters[18:-3]
'stuvw'
В этом примере мы получаем символы, начиная с шестого с конца и заканчивая третьим с конца:
>>> letters[-6:-2]
'uvwx'
Если вы хотите увеличить шаг, укажите его после второго двоеточия, как показано в нескольких следующих примерах.
Каждый седьмой символ с начала до конца:
>>> letters[::7]
'ahov'
Каждый третий символ, начиная со смещения 4 и заканчивая 19-м символом:
>>> letters[4:20:3]
'ehknqt'
Каждый четвертый символ, начиная с 19-го:
>>> letters[19::4]
'tx'
Каждый пятый символ от начала до 20-го:
>>> letters[:21:5]
'afkpu'
(Опять же значение конец должно быть на единицу больше, чем реальное смещение.)
И это еще не все! Если задать отрицательный шаг, удобный разделитель Python дает возможность двигаться в обратную сторону. В следующем примере движение начинается с конца и заканчивается в начале (ни один символ не пропущен):
>>> letters[-1::-1]
'zyxwvutsrqponmlkjihgfedcba'
Оказывается, тот же результат можно получить и другим способом:
>>> letters[::-1]
'zyxwvutsrqponmlkjihgfedcba'
Операция разделения более лояльно относится к некорректно указанным смещениям, чем поиск по индексу с помощью символов []. Если указать смещение меньшее, чем начало строки, оно будет обрабатываться как 0, а если указать смещение большее, чем конец строки, оно будет обработано как –1. Это показано в следующих примерах.
Начиная с –50-го символа и до конца:
>>> letters[-50:]
'abcdefghijklmnopqrstuvwxyz'
Начиная с –51-го символа и заканчивая –50-м:
>>> letters[-51:-50]
''
От начала до 69-го символа:
>>> letters[:70]
'abcdefghijklmnopqrstuvwxyz'
Начиная с 70-го символа и заканчивая 70-м:
>>> letters[70:71]
''
До этого момента мы использовали специальные знаки, такие как +, для работы со строками. Но их не так уж и много. Теперь начнем использовать некоторые из встроенных функций Python: именованные фрагменты кода, которые выполняют определенные операции.
Функция len() подсчитывает количество символов в строке:
>>> len(letters)
26
>>> empty = ""
>>> len(empty)
0
Функцию len() можно использовать и для других типов последовательностей, о чем мы поговорим в главе 7.
В отличие от len(), некоторые функции применимы только к строкам. Для того чтобы использовать строковую функцию, следует ввести имя строки, точку, имя функции и аргументы, которые нужны функции: строка.функция(аргументы). Более подробно об этом поговорим в главе 9.
Встроенная функция split() позволяет разбить строку на список строк меньшего размера с использованием разделителя. Со списками вы познакомитесь в следующей главе. Список — это последовательность значений, разделенных запятыми и заключенных в квадратные скобки:
>>> tasks = 'get gloves,get mask,give cat vitamins,call ambulance'
>>> tasks.split(',')
['get gloves', 'get mask', 'give cat vitamins', 'call ambulance']
В предыдущем примере строка имела имя tasks, а строковая функция называлась split() и имела один аргумент-разделитель ','. Если вы не укажете разделитель, функция split() будет использовать любую последовательность пробелов, а также символы новой строки и табуляцию:
>>> tasks.split()
['get', 'gloves,get', 'mask,give', 'cat', 'vitamins,call', 'ambulance']
При вызове функции split без аргументов круглые скобки все равно надо ставить — именно так Python понимает, что вы вызываете функцию.
Легко догадаться, что функция join() является противоположностью функции split(): она объединяет список строк в одну строку. Вызов функции выглядит немного запутанно, поскольку сначала вы указываете строку, которая объединяет остальные, а затем — список строк для объединения: string.join(list). Таким образом, чтобы объединить строки списка lines, разделенные символами новой строки, вам нужно написать '\n'.join(lines). В следующем примере мы объединим в список несколько имен, разделив их запятыми и пробелами:
>>> crypto_list = ['Yeti', 'Bigfoot', 'Loch Ness Monster']
>>> crypto_string = ', '.join(crypto_list)
>>> print('Found and signing book deals:', crypto_string)
Found and signing book deals: Yeti, Bigfoot, Loch Ness Monster
Функция replace() предназначена для замены одной подстроки другой. Вы указываете старую подстроку, новую подстроку и то, сколько экземпляров старой подстроки нужно заменить. Если вы пропустите последний аргумент, функция заменит все экземпляры. В этом примере только одна строка ('duck') сопоставляется и заменяется:
>>> setup = "a duck goes into a bar..."
>>> setup.replace('duck', 'marmoset')
'a marmoset goes into a bar...'
>>> setup
'a duck goes into a bar...'
Здесь заменим до 100 экземпляров:
>>> setup.replace('a ', 'a famous ', 100)
'a famous duck goes into a famous bar...'
Если вы точно знаете, какую подстроку или подстроки хотите заменить, функция replace() окажется для вас хорошим выбором. Но будьте осторожны: если бы во втором примере вы заменили строку из одного символа 'а', а не строку из двух символов 'а' (после а идет пробел), символы 'а' заменились бы и в середине слов:
>>> setup.replace('a', 'a famous', 100)
'a famous duck goes into a famous ba famousr...'
Иногда вам нужно убедиться в том, что подстрока является целым словом, началом слова и т.п. В такой ситуации понадобятся регулярные выражения. Они подробно описаны в главе 12.
Нередко требуется убрать из строки начальные или конечные символы отступа, чаще всего пробелы. Представленная здесь функция strip() подразумевает, что вы хотите избавиться от символов-пробелов ('', '\t', '\n'), если только вы не предоставите ей аргумент. Функция strip() удаляет символы с обоих концов строки, lstrip() — только в начале, а rstrip() — только в конце. Давайте представим, что строковая переменная world содержит строку earth, окруженную пробелами:
>>> world = " earth "
>>> world.strip()
'earth'
>>> world.strip(' ')
'earth'
>>> world.lstrip()
'earth '
>>> world.rstrip()
' earth'
Если искомого символа в строке нет, ничего не происходит:
>>> world.strip('!')
' earth '
Кроме отсутствия аргумента (когда подразумевается, что нужно найти пробелы) или отдельного символа, возможна и ситуация, когда функция strip() удалит все символы из последовательности:
>>> blurt = "What the...!!?"
>>> blurt.strip('.?!')
'What the'
В приложении Д представлены отдельные определения групп символов, которые можно использовать для передачи в функцию strip():
>>> import string
>>> string.whitespace
' \t\n\r\x0b\x0c'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> blurt = "What the...!!?"
>>> blurt.strip(string.punctuation)
'What the'
>>> prospector = "What in tarnation ...??!!"
>>> prospector.strip(string.whitespace + string.punctuation)
'What in tarnation'
Python содержит большой набор функций для работы со строками. Рассмотрим принцип работы самых распространенных из них. Тестовым объектом станет следующая строка, содержащая текст бессмертного стихотворения «What Is Liquid?» Маргарет Кавендиш, герцогини Ньюкасл:
>>> poem = '''All that doth flow we cannot liquid name
Or else would fire and water be the same;
But that is liquid which is moist and wet
Fire that property can never get.
Then 'tis not cold that doth the fire put out
But 'tis the wet that makes it die, no doubt.'''
Вдохновляет!
Для начала получим первые 13 символов (их смещения лежат в диапазоне от 0 до 12):
>>> poem[:13]
'All that doth'
Сколько символов содержит это стихотворение? (Пробелы и символы новой строки учитываются.)
>>> len(poem)
250
Начинается ли стихотворение с All?
>>> poem.startswith('All')
True
Заканчивается ли оно фразой That’s all, folks!?
>>> poem.endswith('That\'s all, folks!')
False
В Python есть два метода поиска смещения подстроки — find() и index(). У каждого метода имеется возможность начинать поиск или с начала, или с конца. В случае если подстрока присутствует в строке, они работают одинаково. Если подстрока не найдена, метод find() возвращает −1, а метод index() генерирует исключение.
Найдем смещение первого появления в стихотворении слова the:
>>> word = 'the'
>>> poem.find(word)
73
>>> poem.index(word)
73
А теперь — последнего:
>>> word = 'the'
>>> poem.rfind(word)
214
>>> poem.rindex(word)
214
Но что, если подстроки нет?
>>> word = "duck"
>>> poem.find(word)
-1
>>> poem.rfind(word)
-1
>>> poem.index(word)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
>>> poem.rfind(word)
-1
>>> poem.rindex(word)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
Сколько раз встречается трехбуквенное сочетание the?
>>> word = 'the'
>>> poem.count(word)
3
Являются ли все символы в стихотворении буквами или цифрами?
>>> poem.isalnum()
False
Нет, в стихотворении имеются еще и знаки препинания.
В этом разделе мы рассмотрим еще несколько примеров использования встроенных функций. В качестве тестовой выберем следующую строку:
>>> setup = 'a duck goes into a bar...'
Удалим символ . с обоих концов строки:
>>> setup.strip('.')
'a duck goes into a bar'
Поскольку строки неизменяемы, ни в одном из этих примеров строка setup на самом деле не изменяется. Просто берется значение переменной setup, над ним выполняется некоторое действие, а затем результат возвращается в виде новой строки.
Напишем первое слово с большой буквы:
>>> setup.capitalize()
'A duck goes into a bar...'
Напишем все слова с большой буквы:
>>> setup.title()
'A Duck Goes Into A Bar...'
Запишем все слова большими буквами:
>>> setup.upper()
'A DUCK GOES INTO A BAR...'
Запишем все слова строчными буквами:
>>> setup.lower()
'a duck goes into a bar...'
Сменим регистры букв на противоположные:
>>> setup.swapcase()
'a DUCK GOES INTO A BAR...'
Теперь поработаем с функциями выравнивания. Строка выравнивается в пределах указанного общего количества пробелов (в данном примере 30).
Отцентрируем строку в промежутке из 30 пробелов:
>>> setup.center(30)
' a duck goes into a bar... '
Выровняем ее по левому краю:
>>> setup.ljust(30)
'a duck goes into a bar... '
А теперь по правому:
>>> setup.rjust(30)
' a duck goes into a bar...'
Далее рассмотрим другие способы выравнивания строки.
Вы уже видели, как можно конкатенировать строки с помощью оператора +. А теперь узнаете, как интерполировать данные в строки, используя разные форматы. Этим приемом можно пользоваться, чтобы создавать отчеты и другие документы, для которых важен определенный внешний вид.
Помимо функций, рассмотренных в предыдущем разделе, Python имеет три способа форматирования строк:
•старый стиль (поддерживается в Python 2 и 3);
• новый стиль (Python 2.6 и выше);
•f-строки (Python 3.6 и выше).
Старый стиль форматирования строк имеет форму строка%данные. Внутри строки находятся интерполяционные последовательности. В табл. 5.1 показано, что самая простая последовательность — это символ % и буква. Буква указывает на тип данных, которые должны быть отформатированы.
Таблица 5.1. Типы преобразования
%s | Строка |
%d | Целое число в десятичной системе счисления |
%x | Целое число в шестнадцатеричной системе счисления |
%o | Целое число в восьмеричной системе счисления |
%f | Число с плавающей точкой в десятичной системе счисления |
%e | Число с плавающей точкой в шестнадцатеричной системе счисления |
%g | Число с плавающей точкой в восьмеричной системе счисления |
%% | Символ % |
Вы можете использовать последовательность %s для любого типа данных — Python отформатирует их как строку без дополнительных пробелов.
Рассмотрим несколько примеров. Сначала целое число:
>>> '%s' % 42
'42'
>>> '%d' % 42
'42'
>>> '%x' % 42
'2a'
>>> '%o' % 42
'52'
Число с плавающей точкой:
>>> '%s' % 7.03
'7.03'
>>> '%f' % 7.03
'7.030000'
>>> '%e' % 7.03
'7.030000e+00'
>>> '%g' % 7.03
'7.03'
Целое число и символ %:
>>> '%d%%' % 100
'100%'
Интерполяция некоторых строк и целых чисел:
>>> actor = 'Richard Gere'
>>> cat = 'Chester'
>>> weight = 28
>>> "My wife's favorite actor is %s" % actor
"My wife's favorite actor is Richard Gere"
>>> "Our cat %s weighs %s pounds" % (cat, weight)
'Our cat Chester weighs 28 pounds'
Последовательность %s внутри строки означает, что нужно интерполировать строку. Количество использованных символов % должно совпадать с количеством объектов, расположенных после %. Один элемент, такой как actor, располагается сразу после символа %. Если таких объектов несколько, они должны быть сгруппированы в кортеж (читайте подробнее в главе 7), то есть их нужно заключить в скобки, разделив запятыми. Например, (cat,weight).
Несмотря на то что переменная weight целочисленная, последовательность %s внутри строки преобразует ее в строку.
Вы можете добавить другие значения между % и определением типа, чтобы указать минимальную и максимальную ширину, а также выравнивание и заполнение символами. Эти конструкции похожи на своего рода небольшой язык, достаточно ограниченный по сравнению с тем, который будет представлен в следующих двух подразделах. Какие это значения:
• в начале располагается символ '%';
• опциональный символ выравнивания: ничего или '+' означают выравнивание по правому краю, а '−' — по левому;
• опциональное поле мин_ширина, в котором указывается длина строки;
• опциональный символ '.', разделяющий поля мин_ширина и макс_символы;
• опциональное поле макс_символы (используется в том случае, если тип преобразования s), в котором указывается, сколько символов значения нужно вывести на экран. Если тип преобразования f, в этом поле указывается точность (сколько символов выводится после десятичной точки);
• символ, определяющий тип преобразования, из табл. 5.1.
Выглядит запутанно. Рассмотрим примеры для строки:
>>> thing = 'woodchuck'
>>> '%s' % thing
'woodchuck'
>>> '%12s' % thing
' woodchuck'
>>> '%+12s' % thing
' woodchuck'
>>> '%-12s' % thing
'woodchuck '
>>> '%.3s' % thing
'woo'
>>> '%12.3s' % thing
' woo'
>>> '%-12.3s' % thing
'woo '
Теперь рассмотрим примеры для чисел с плавающей точкой (%f):
>>> thing = 98.6
>>> '%f' % thing
'98.600000'
>>> '%12f' % thing
' 98.600000'
>>> '%+12f' % thing
' +98.600000'
>>> '%-12f' % thing
'98.600000 '
>>> '%.3f' % thing
'98.600'
>>> '%12.3f' % thing
' 98.600'
>>> '%-12.3f' % thing
'98.600 '
А теперь — для целых чисел (%d):
>>> thing = 9876
>>> '%d' % thing
'9876'
>>> '%12d' % thing
' 9876'
>>> '%+12d' % thing
' +9876'
>>> '%-12d' % thing
'9876 '
>>> '%.3d' % thing
'9876'
>>> '%12.3d' % thing
' 9876'
>>> '%-12.3d' % thing
'9876 '
Для целых чисел конструкция %+12d заставляет вывести знак числа, при этом строки формата, содержащие конструкцию .3, ни на что не влияют, поскольку предназначены для чисел с плавающей точкой.
Старый стиль форматирования все еще поддерживается, и в Python 2, который остановился на версии 2.7, он будет поддерживаться всегда. В Python 3 применяется новый стиль форматирования. Если у вас установлен Python 3.6 или выше, рекомендую воспользоваться f-строками (см. подраздел «Самый новый стиль: f-строки» далее в этой главе).
Новый стиль форматирования имеет вид строка.format(данные).
Строка формата выглядит немного иначе, чем в предыдущем подразделе. Простейший пример использования этого стиля показан здесь:
>>> thing = 'woodchuck'
>>> '{}'.format(thing)
'woodchuck'
Аргументы функции format() должны идти в том порядке, в котором расставлены заполнители {} в строке формата:
>>> thing = 'woodchuck'
>>> place = 'lake'
>>> 'The {} is in the {}.'.format(thing, plкace)
'The woodchuck is in the lake.'
В новом стиле форматирования вы также можете указать позицию аргументов следующим образом:
>>> 'The {1} is in the {0}.'.format(place, thing)
'The woodchuck is in the lake.'
Значение 0 относится к первому аргументу place, а 1 — к thing.
Аргументы функции format() могут быть именованными:
>>> 'The {thing} is in the {place}'.format(thing='duck', place='bathtub')
'The duck is in the bathtub'
Они также могут быть словарями:
>>> d = {'thing': 'duck', 'place': 'bathtub'}
В следующем примере {0} — это первый аргумент функции format() (словарь d):
>>> 'The {0[thing]} is in the {0[place]}.'.format(d)
'The duck is in the bathtub.'
В этих примерах аргументы выводились в формате, установленном по умолчанию. В новом стиле форматирования строка формата несколько отличается от той, которая использовалась в старом стиле. Ее отличия:
• начальное двоеточие (':');
• опциональный символ-заполнитель (по умолчанию ''), которым заполняется строка, если ее длина меньше, чем мин_ширина;
• опциональный символ выравнивания. В этот раз вариантом по умолчанию является выравнивание по левому краю. Символ '<' означает выравнивание по левому краю, символ '>' — по правому, а символ '^' означает выравнивание по центру;
• опциональный знак для чисел. Отсутствие значения приведет к тому, что знак будет отображаться только для отрицательных чисел. Символ '' означает, что для отрицательных чисел будет добавляться знак -, а для положительных — пробел ('');
• необязательное поле мин_ширина. Необязательный символ ('.') используется для отделения значений полей мин_ширина и макс_символы;
• необязательное поле макс_символы;
•тип преобразования.
>>> thing = 'wraith'
>>> place = 'window'
>>> 'The {} is at the {}'.format(thing, place)
'The wraith is at the window'
>>> 'The {:10s} is at the {:10s}'.format(thing, place)
'The wraith is at the window '
>>> 'The {:<10s} is at the {:<10s}'.format(thing, place)
'The wraith is at the window '
>>> 'The {:^10s} is at the {:^10s}'.format(thing, place)
'The wraith is at the window '
>>> 'The {:>10s} is at the {:>10s}'.format(thing, place)
'The wraith is at the window'
>>> 'The {:!^10s} is at the {:!^10s}'.format(thing, place)
'The !!wraith!! is at the !!window!!'
На данный момент для форматирования строк рекомендуется использовать f-строки, которые появились в версии Python 3.6.
Чтобы создать f-строку, нужно сделать следующее:
• ввести букву f или F перед первой кавычкой;
• поместить имена переменной или выражения в фигурные скобки ({}), чтобы их значения попали в строку.
Этот способ форматирования похож на новый стиль, но здесь не задействованы функция format(), пустые скобки ({}) и позиционные аргументы ({1}) в строке формата.
>>> thing = 'wereduck'
>>> place = 'werepond'
>>> f'The {thing} is in the {place}'
'The wereduck is in the werepond'
Как я уже говорил, в фигурных скобках можно размещать и выражения:
>>> f'The {thing.capitalize()} is in the {place.rjust(20)}'
'The Wereduck is in the werepond'
Таким образом, то, что вы могли делать внутри функции format() из предыдущего раздела, можно сделать и здесь внутри фигурных скобок в главной строке. Это упрощает чтение.
Для f-строк используется такой же язык форматирования (ширина, заполнитель, выравнивание), как и в новом стиле. Выражения размещаются после двоеточия:
>>> f'The {thing:>20} is in the {place:.^20}'
'The wereduck is in the ......werepond......'
Начиная с версии Python 3.8, f-строки позволяют выводить не только значения переменных, но и их имена. Это очень удобно при отладке. Идея заключается в том, чтобы поставить знак = после имени переменной, размещенного в фигурных скобках:
>>> f'{thing =}, {place =}'
thing = 'wereduck', place = 'werepond'
Этот прием также работает и для выражений. Каждое выражение будет выведено полностью:
>>> f'{thing[-4:] =}, {place.title() =}'
thing[-4:] = 'duck', place.title() = 'Werepond'
Наконец, после знака = можно поставить двоеточие, за которым будут следовать аргументы, такие как длины и выравнивания:
>>> f'{thing = :>4.4}'
thing = 'were'
В Python имеется гораздо больше функций для работы со строками, нежели я сейчас описал. Некоторые из них мы рассмотрим в следующих главах (особенно в главе 12), но описания всех можно найти в стандартной документации ().
Следующая глава посвящена циклам в Python.
5.1. Напишите с заглавной буквы слово, которое начинается с буквы m:
>>> song = """When an eel grabs your arm,
... And it causes great harm,
... That's - a moray!"""
5.2. Выведите на экран все вопросы из списка, а также правильные ответы в таком виде:
Q: вопрос
A: ответ
>>> questions = [
... "We don't serve strings around here. Are you a string?",
... "What is said on Father's Day in the forest?",
... "What makes the sound 'Sis! Boom! Bah!'?"
... ]
>>> answers = [
... "An exploding sheep.",
... "No, I'm a frayed knot.",
... "'Pop!' goes the weasel."
... ]
5.3. Выведите на экран следующее стихотворение, используя старый стиль форматирования. Подставьте в него такие строки: 'roastbeef', 'ham', 'head' и 'clam':
My kitty cat likes %s,
My kitty cat likes %s,
My kitty cat fell on his %s
And now thinks he's a %s.
5.4. Напишите письмо с использованием нового стиля форматирования. Сохраните предложенную строку в переменной letter (она понадобится вам в упражнении ниже):
Dear {salutation} {name},
Thank you for your letter. We are sorry that our {product}
{verbed} in your {room}. Please note that it should never
be used in a {room}, especially near any {animals}.
Send us your receipt and {amount} for shipping and handling.
We will send you another {product} that, in our tests,
is {percent}% less likely to have {verbed}.
Thank you for your support.
Sincerely,
{spokesman}
{job_title}
5.5. Присвойте значения переменным 'salutation', 'name', 'product', 'verbed' (глагол в прошедшем времени), 'room', 'animals', 'percent', 'spokesman' и 'job_title'. С помощью функции letter.format() выведите на экран значение переменной letter, в которую подставлены эти значения.
5.6. После проведения публичных опросов с целью выбора имени появились: английская подводная лодка Boaty McBoatface, австралийская беговая лошадь Horsey McHorseface и шведский поезд Trainy McTrainface. Используйте форматирование с символом % для того, чтобы вывести на экран победившие имена для утки, тыквы и шпица.
5.7. Сделайте то же самое с помощью функции format().
5.8. А теперь еще раз с использованием f-строк.