You are currently viewing Строки и символьные данные в Python

Строки и символьные данные в Python

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

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

Вы также познакомитесь с двумя другими объектами Python, используемыми для представления необработанных байтовых данных, bytes byte array типами и.

Манипуляция строками

В разделах ниже перечислены операторы, методы и функции, доступные для работы со строками.

Строковые операторы

Вы уже видели операторы + и * применяли их к числовым операндам в учебнике по операторам и выражениям в Python. Эти два оператора также могут быть применены к строкам.

Оператор +

+ Оператор объединяет строки. Он возвращает строку, состоящую из соединенных вместе операндов, как показано здесь:>>>

>>> s = 'foo'
>>> t = 'bar'
>>> u = 'baz'

>>> s + t
'foobar'
>>> s + t + u
'foobarbaz'

>>> print('Go team' + '!!!')
Go team!!!

Оператор *

  • Оператор создает несколько копий строки. Если s является строкой и n целым числом, любое из следующих выражений возвращает строку, состоящую из n соединенных копий s:

s * n
n * s

Вот примеры обеих форм:>>>

>>> s = 'foo.'

>>> s * 4
'foo.foo.foo.foo.'
>>> 4 * s
'foo.foo.foo.foo.'

Операнд множителя nдолжен быть целым числом. Вы могли бы подумать, что это должно быть положительное целое число, но забавно, что оно может быть нулевым или отрицательным, и в этом случае результатом будет пустая строка:>>>

>>> 'foo' * -8
''

Если бы вы создали строковую переменную и инициализировали ее пустой строкой , присвоив ей значение 'foo' * -8, любой бы справедливо подумал, что вы немного глупы. Но это сработает.

Оператор in

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

>>> s = 'foo'

>>> s in 'That\'s food for thought.'
True
>>> s in 'That\'s good for now.'
False

Существует также not in оператор, который делает обратное:>>>

>>> 'z' not in 'abc'
True
>>> 'z' not in 'xyz'
False

Встроенные строковые функции

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

ФункцияОписание
chr()Преобразует целое число в символ
ord()Преобразует символ в целое число
len()Возвращает длину строки
str()Возвращает строковое представление объекта

Они более подробно рассматриваются ниже.

ord(c)

Возвращает целое значение для данного символа.

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

Самая простая схема в общем использовании называется ASCII. Он охватывает распространенные латинские символы, с которыми вы, вероятно, больше всего привыкли работать. Для этих символов ord(c) возвращает значение ASCII для символа c:>>>

>>> ord('a')
97
>>> ord('#')
35

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

Unicode-это амбициозный стандарт, который пытается предоставить цифровой код для каждого возможного символа на всех возможных языках и на всех возможных платформах. Python 3 широко поддерживает Юникод, включая использование символов Юникода в строках.

Дополнительные сведения см. в разделе Кодировки Юникода и символов в Python: Краткое руководство и поддержка Юникода Python в документации по Python.

Пока вы остаетесь в области общих символов, существует небольшая практическая разница между ASCII и Unicode. Но ord() функция также будет возвращать числовые значения для символов Юникода:>>>

>>> ord('€')
8364
>>> ord('∑')
8721

chr(n)

Возвращает символьное значение для заданного целого числа.

chr() делает обратное ord(). Заданное числовое значение nchr(n) возвращает строку , представляющую символ, соответствующий n:>>>

>>> chr(97)
'a'
>>> chr(35)
'#'

chr() также обрабатывает символы Юникода:>>>

>>> chr(8364)
'€'
>>> chr(8721)
'∑'

len(s)

Возвращает длину строки.

С len() помощью вы можете проверить длину строки Python. len(s) возвращает количество символов в s:>>>

>>> s = 'I am a string.'
>>> len(s)
14

str(obj)

Возвращает строковое представление объекта.

Практически любой объект в Python может быть представлен в виде строки. str(obj) возвращает строковое представление объекта obj:>>>

>>> str(49.2)
'49.2'
>>> str(3+4j)
'(3+4j)'
>>> str(3 + 29)
'32'
>>> str('foo')
'foo'

Индексирование строк

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

В Python строки представляют собой упорядоченные последовательности символьных данных и, следовательно, могут быть проиндексированы таким образом. Доступ к отдельным символам в строке можно получить, указав имя строки, за которым следует число в квадратных скобках ([]).

Индексация строк в Python основана на нуле: первый символ в строке имеет индекс 0, следующий 1-индекс и так далее. Индекс последнего символа будет равен длине строки минус единица.

Например, схематическое представление индексов строки 'foobar' будет выглядеть следующим образом:

Доступ к отдельным символам можно получить по индексу следующим образом:>>>

>>> s = 'foobar'

>>> s[0]
'f'
>>> s[1]
'o'
>>> s[3]
'b'
>>> len(s)
6
>>> s[len(s)-1]
'r'

Попытка индексирования за пределами конца строки приводит к ошибке:>>>

>>> s[6]
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    s[6]
IndexError: string index out of range

Строковые индексы также могут быть указаны с отрицательными числами, и в этом случае индексация происходит с конца строки в обратном направлении: -1 относится к последнему символу, -2 предпоследнему символу и так далее. Вот та же самая диаграмма, показывающая как положительные, так и отрицательные индексы в строке 'foobar':

Вот несколько примеров отрицательной индексации:>>>

>>> s = 'foobar'

>>> s[-1]
'r'
>>> s[-2]
'a'
>>> len(s)
6
>>> s[-len(s)]
'f'

Попытка индексирования с отрицательными числами после начала строки приводит к ошибке:>>>

>>> s[-7]
Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    s[-7]
IndexError: string index out of range

Для любой непустой строки ss[len(s)-1] и s[-1] оба возвращают последний символ. Нет никакого индекса, который имел бы смысл для пустой строки.

Нарезка струн

Python также допускает форму синтаксиса индексирования, которая извлекает подстроки из строки, известную как нарезка строк. Если s это строка, выражение формы s[m:n] возвращает часть s, начинающуюся с позиции m, и до, но не включая позицию n:>>>

>>> s = 'foobar'
>>> s[2:5]
'oba'

Помните: строковые индексы основаны на нуле. Первый символ в строке имеет индекс 0. Это относится как к стандартному индексированию, так и к нарезке.

Опять же, второй индекс указывает первый символ, который не включен в результат,—символ 'r'(s[5]) в приведенном выше примере. Это может показаться немного неинтуитивным, но это дает такой результат, который имеет смысл: выражение s[m:n] вернет подстроку n - m длиной в символы, в данном случае, 5 - 2 = 3.

Если вы опустите первый индекс, срез начнется в начале строки. Таким образом, s[:m] и s[0:m]эквивалентны:>>>

>>> s = 'foobar'

>>> s[:4]
'foob'
>>> s[0:4]
'foob'

Аналогично, если вы опустите второй индекс , как в s[n:], срез простирается от первого индекса до конца строки. Это приятная, лаконичная альтернатива более громоздким s[n:len(s)]:>>>

>>> s = 'foobar'

>>> s[2:]
'obar'
>>> s[2:len(s)]
'obar'

Для любой строки s и любого целого n числа (0 ≤ n ≤ len(s)s[:n] + s[n:] будет равно s:>>>

>>> s = 'foobar'

>>> s[:4] + s[4:]
'foobar'
>>> s[:4] + s[4:] == s
True

Опущение обоих индексов возвращает исходную строку целиком. Буквально. Это не копия, это ссылка на исходную строку:>>>

>>> s = 'foobar'
>>> t = s[:]
>>> id(s)
59598496
>>> id(t)
59598496
>>> s is t
True

Если первый индекс в срезе больше или равен второму индексу, Python возвращает пустую строку. Это еще один запутанный способ сгенерировать пустую строку, на случай, если вы ее искали:>>>

>>> s[2:2]
''
>>> s[4:2]
''

Отрицательные индексы также можно использовать при нарезке. -1 относится к последнему символу, -2 предпоследнему и так далее, как и при простом индексировании. На приведенной ниже диаграмме показано, как вырезать подстроку 'oob' из строки 'foobar', используя как положительные, так и отрицательные индексы:

Вот соответствующий код на Python:>>>

>>> s = 'foobar'

>>> s[-5:-2]
'oob'
>>> s[1:4]
'oob'
>>> s[-5:-2] == s[1:4]
True

Указание шага в строковом срезе

Есть еще один вариант синтаксиса среза, который следует обсудить. Добавление дополнительного :и третьего индекса обозначает шаг (также называемый шагом), который указывает, сколько символов нужно перепрыгнуть после извлечения каждого символа в срезе.

Например, для строки 'foobar' фрагмент 0:6:2 начинается с первого символа и заканчивается последним символом (всей строкой), и каждый второй символ пропускается. Это показано на следующей диаграмме:

Аналогично, 1:6:2 указывает фрагмент, начинающийся со второго символа (индекса 1) и заканчивающийся последним символом, и снова значение шага 2 приводит к пропуску всех остальных символов:

Иллюстративный код REPL показан здесь:>>>

>>> s = 'foobar'

>>> s[0:6:2]
'foa'

>>> s[1:6:2]
'obr'

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

>>> s = '12345' * 5
>>> s
'1234512345123451234512345'
>>> s[::5]
'11111'
>>> s[4::5]
'55555'

Вы также можете указать отрицательное значение шага, и в этом случае Python делает шаг назад по строке. В этом случае начальный/первый индекс должен быть больше конечного/второго индекса:>>>

>>> s = 'foobar'
>>> s[5:0:-2]
'rbo'

В приведенном выше примере 5:0:-2 означает “начните с последнего символа и сделайте шаг назад 2, вплоть до первого символа , но не включая его”.

Когда вы отступаете назад, если первый и второй индексы опущены, значения по умолчанию меняются интуитивно понятным способом: первый индекс по умолчанию равен концу строки, а второй индекс по умолчанию равен началу. Вот пример:>>>

>>> s = '12345' * 5
>>> s
'1234512345123451234512345'
>>> s[::-5]
'55555'

Это распространенная парадигма для обращения строки:>>>

>>> s = 'If Comrade Napoleon says it, it must be right.'
>>> s[::-1]
'.thgir eb tsum ti ,ti syas noelopaN edarmoC fI'

Интерполяция переменных в строку

В Python версии 3.6 был введен новый механизм форматирования строк. Эта функция формально называется Форматированным строковым литералом, но чаще всего ее называют f-строкой.

Возможности форматирования, предоставляемые f-строками, обширны и не будут подробно рассмотрены здесь. Если вы хотите узнать больше, вы можете ознакомиться с настоящей статьей Python f-Строки Python 3: Улучшенный синтаксис форматирования строк (Руководство). Существует также учебник по форматированному выходу, который появится позже в этой серии, в котором более подробно рассматриваются f-строки.

Одной из простых функций f-строк, которую вы можете начать использовать сразу, является интерполяция переменных. Вы можете указать имя переменной непосредственно в литерале f-строки, и Python заменит имя соответствующим значением.

Например, предположим, что вы хотите отобразить результат арифметического вычисления. Вы можете сделать это с помощью простого print() оператора, разделяющего числовые значения и строковые литералы запятыми:>>>

>>> n = 20
>>> m = 25
>>> prod = n * m
>>> print('The product of', n, 'and', m, 'is', prod)
The product of 20 and 25 is 500

Но это громоздко. Чтобы выполнить то же самое, используя строку f:

  • Укажите строчный f или верхний регистр F непосредственно перед начальной кавычкой строкового литерала. Это говорит Python, что это f-строка вместо стандартной строки.
  • Укажите любые переменные, которые будут интерполироваться в фигурных скобках ({}).

Переделанный с использованием строки f, приведенный выше пример выглядит намного чище:>>>

>>> n = 20
>>> m = 25
>>> prod = n * m
>>> print(f'The product of {n} and {m} is {prod}')
The product of 20 and 25 is 500

Любой из трех механизмов цитирования Python может быть использован для определения строки f:>>>

>>> var = 'Bark'

>>> print(f'A dog says {var}!')
A dog says Bark!
>>> print(f"A dog says {var}!")
A dog says Bark!
>>> print(f'''A dog says {var}!''')
A dog says Bark!

Изменение строк

В двух словах, ты не можешь. Строки являются одним из типов данных, которые Python считает неизменяемыми, то есть не подлежащими изменению. На самом деле, все типы данных, которые вы видели до сих пор, неизменны. (Python предоставляет изменяемые типы данных, как вы скоро увидите.)

Подобное утверждение приведет к ошибке:>>>

>>> s = 'foobar'
>>> s[3] = 'x'
Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    s[3] = 'x'
TypeError: 'str' object does not support item assignment

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

>>> s = s[:3] + 'x' + s[4:]
>>> s
'fooxar'

Для этого также существует встроенный строковый метод:>>>

>>> s = 'foobar'
>>> s = s.replace('b', 'x')
>>> s
'fooxar'

Читайте дальше для получения дополнительной информации о встроенных строковых методах!

Встроенные строковые методы

Из учебника по переменным в Python вы узнали, что Python-это в высшей степени объектно-ориентированный язык. Каждый элемент данных в программе на Python является объектом.

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

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

Синтаксис вызова метода для объекта выглядит следующим образом:

obj.foo(<args>)

Это вызывает метод .foo() для объекта obj<args> указывает аргументы, переданные методу (если таковые имеются).

Вы узнаете гораздо больше об определении и вызове методов позже в обсуждении объектно-ориентированного программирования. На данный момент цель состоит в том, чтобы представить некоторые из наиболее часто используемых встроенных методов, поддерживаемых Python для работы со строковыми объектами.

В следующих определениях методов аргументы, указанные в квадратных скобках ([]), являются необязательными.

Преобразование обращений

Методы в этой группе выполняют преобразование регистра в целевой строке.

s.capitalize()

Вводит целевую строку с заглавной буквы.

s.capitalize() возвращает копию s с первым символом, преобразованным в верхний регистр, и всеми остальными символами, преобразованными в нижний регистр:>>>

>>> s = 'foO BaR BAZ quX'
>>> s.capitalize()
'Foo bar baz qux'

Неалфавитные символы остаются неизменными:>>>

>>> s = 'foo123#BAR#.'
>>> s.capitalize()
'Foo123#bar#.'

s.lower()

Преобразует алфавитные символы в строчные.

s.lower() возвращает копию sсо всеми буквенными символами, преобразованными в нижний регистр:>>>

>>> 'FOO Bar 123 baz qUX'.lower()
'foo bar 123 baz qux'

s.swapcase()

Меняет местами регистр буквенных символов.

s.swapcase() возвращает копию sс буквенными символами верхнего регистра, преобразованными в нижний регистр, и наоборот:>>>

>>> 'FOO Bar 123 baz qUX'.swapcase()
'foo bAR 123 BAZ Qux'

s.title()

Преобразует целевую строку в “регистр заголовка”.

s.title() возвращает копию s, в которой первая буква каждого слова преобразована в верхний регистр, а остальные буквы-в нижний:>>>

>>> 'the sun also rises'.title()
'The Sun Also Rises'

Этот метод использует довольно простой алгоритм. Он не пытается провести различие между важными и неважными словами, и он не изящно обрабатывает апострофы, притяжательные или аббревиатуры:>>>

>>> "what's happened to ted's IBM stock?".title()
"What'S Happened To Ted'S Ibm Stock?"

s.upper()

Преобразует алфавитные символы в заглавные.

s.upper() возвращает копию sсо всеми буквенными символами, преобразованными в верхний регистр:>>>

>>> 'FOO Bar 123 baz qUX'.upper()
'FOO BAR 123 BAZ QUX'

Найти и заменить

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

Каждый метод в этой группе поддерживает необязательные <start><end> аргументы и. Они интерпретируются как для нарезки строк: действие метода ограничено частью целевой строки, начинающейся с позиции символа <start> и продолжающейся до позиции символа, но не включающей <end> ее . Если <start> указано, но <end> не указано, метод применяется к части целевой строки от <start> конца до конца строки.

s.count(<sub>[, <start>[, <end>]])

Подсчитывает вхождения подстроки в целевой строке.

s.count(<sub>) возвращает количество неперекрывающихся вхождений подстроки <sub>вs:>>>

>>> 'foo goo moo'.count('oo')
3

Количество ограничено количеством вхождений в подстроке , указанной <start> и <end>, если они указаны:>>>

>>> 'foo goo moo'.count('oo', 0, 8)
2

s.endswith(<suffix>[, <start>[, <end>]])

Определяет, заканчивается ли целевая строка заданной подстрокой.

s.endswith(<suffix>) возвращает True, если s заканчивается указанным <suffix> и False в противном случае:>>>

>>> 'foobar'.endswith('bar')
True
>>> 'foobar'.endswith('baz')
False

Сравнение ограничивается подстрокой , указанной <start> и <end>, если они указаны:>>>

>>> 'foobar'.endswith('oob', 0, 4)
True
>>> 'foobar'.endswith('oob', 2, 4)
False

s.find(<sub>[, <start>[, <end>]])

Выполняет поиск в целевой строке заданной подстроки.

Вы можете использовать.find(), чтобы узнать, содержит ли строка Python определенную подстроку. s.find(<sub>) возвращает наименьший индекс в sтом месте, где найдена подстрока <sub>:>>>

>>> 'foo bar foo baz foo qux'.find('foo')
0

Этот метод возвращает -1 значение, если указанная подстрока не найдена:>>>

>>> 'foo bar foo baz foo qux'.find('grault')
-1

Поиск ограничен подстрокой , указанной <start> и <end>, если они указаны:>>>

>>> 'foo bar foo baz foo qux'.find('foo', 4)
8
>>> 'foo bar foo baz foo qux'.find('foo', 4, 7)
-1

s.index(<sub>[, <start>[, <end>]])

Выполняет поиск в целевой строке заданной подстроки.

Этот метод идентичен .find(), за исключением того, что он вызывает исключение, если <sub> не найден, а не возвращает-1:>>>

>>> 'foo bar foo baz foo qux'.index('grault')
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    'foo bar foo baz foo qux'.index('grault')
ValueError: substring not found

s.rfind(<sub>[, <start>[, <end>]])

Выполняет поиск в целевой строке заданной подстроки, начиная с конца.

s.rfind(<sub>) возвращает самый высокий индекс в sтом месте, где найдена подстрока <sub>:>>>

>>> 'foo bar foo baz foo qux'.rfind('foo')
16

Как .find() и в случае , если подстрока не найдена, -1 возвращается:>>>

>>> 'foo bar foo baz foo qux'.rfind('grault')
-1

Поиск ограничен подстрокой , указанной <start> и <end>, если они указаны:>>>

>>> 'foo bar foo baz foo qux'.rfind('foo', 0, 14)
8
>>> 'foo bar foo baz foo qux'.rfind('foo', 10, 14)
-1

s.rindex(<sub>[, <start>[, <end>]])

Выполняет поиск в целевой строке заданной подстроки, начиная с конца.

Этот метод идентичен .rfind(), за исключением того, что он вызывает исключение, если <sub> не найден, а не возвращает-1:>>>

>>> 'foo bar foo baz foo qux'.rindex('grault')
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    'foo bar foo baz foo qux'.rindex('grault')
ValueError: substring not found

s.startswith(<prefix>[, <start>[, <end>]])

Определяет, начинается ли целевая строка с заданной подстроки.

При использовании метода Python .startswith()s.startswith(<suffix>) возвращается True, если s начинается с указанного <suffix> и False в противном случае:>>>

>>> 'foobar'.startswith('foo')
True
>>> 'foobar'.startswith('bar')
False

Сравнение ограничивается подстрокой , указанной <start> и <end>, если они указаны:>>>

>>> 'foobar'.startswith('bar', 3)
True
>>> 'foobar'.startswith('bar', 3, 2)
False

Классификация персонажей

Методы в этой группе классифицируют строку на основе содержащихся в ней символов.

s.isalnum()

Определяет, состоит ли целевая строка из буквенно-цифровых символов.

s.isalnum() возвращает True значение, если s оно непустое и все его символы являются буквенно-цифровыми (либо буквой, либо цифрой), и False в противном случае:>>>

>>> 'abc123'.isalnum()
True
>>> 'abc$123'.isalnum()
False
>>> ''.isalnum()
False

s.isalpha()

Определяет, состоит ли целевая строка из буквенных символов.

s.isalpha() возвращает True значение, если s оно непустое и все его символы являются буквенными, а False в противном случае:>>>

>>> 'ABCabc'.isalpha()
True
>>> 'abc123'.isalpha()
False

s.isdigit()

Определяет, состоит ли целевая строка из цифровых символов.

Вы можете использовать метод .isdigit() Python, чтобы проверить, состоит ли ваша строка только из цифр. s.isdigit() возвращает True значение, если s оно непустое и все его символы являются цифровыми цифрами, а False в противном случае:>>>

>>> '123'.isdigit()
True
>>> '123abc'.isdigit()
False

s.isidentifier()

Определяет, является ли целевая строка допустимым идентификатором Python.

s.isidentifier() возвращает True, если s является допустимым идентификатором Python в соответствии с определением языка, и False в противном случае:>>>

>>> 'foo32'.isidentifier()
True
>>> '32foo'.isidentifier()
False
>>> 'foo$32'.isidentifier()
False

Примечание: .isidentifier() будет возвращена True строка, соответствующая ключевому слову Python, даже если на самом деле это не будет допустимым идентификатором:>>>

>>> 'and'.isidentifier()
True

Вы можете проверить , соответствует ли строка ключевому слову Python, используя вызываемую функцию iskeyword(), которая содержится в вызываемом модуле keyword. Один из возможных способов сделать это показан ниже:>>>

>>> from keyword import iskeyword
>>> iskeyword('and')
True

Если вы действительно хотите убедиться, что строка будет служить допустимым идентификатором Python, вам следует проверить, что .isidentifier() есть True и что iskeyword() есть False.

Смотрите раздел Модули и пакеты Python — Введение, чтобы узнать больше о модулях Python.

s.islower()

Определяет, являются ли буквенные символы целевой строки строчными.

s.islower() возвращает True значение, если s оно непустое и все содержащиеся в нем буквенные символы являются строчными, и False в противном случае. Неалфавитные символы игнорируются:>>>

>>> 'abc'.islower()
True
>>> 'abc1$d'.islower()
True
>>> 'Abc1$D'.islower()
False

s.isprintable()

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

s.isprintable() возвращает True значение, если s оно пустое или все содержащиеся в нем алфавитные символы доступны для печати. Он возвращается False, если s содержит хотя бы один непечатаемый символ. Неалфавитные символы игнорируются:>>>

>>> 'a\tb'.isprintable()
False
>>> 'a b'.isprintable()
True
>>> ''.isprintable()
True
>>> 'a\nb'.isprintable()
False

Примечание: Это единственный .isxxxx() метод, который возвращает True if s пустую строку. Все остальные возвращаются False за пустой строкой.

s.isspace()

Определяет, состоит ли целевая строка из пробелов.

s.isspace() возвращает True значение, если s оно непусто и все символы являются пробелами, и False в противном случае.

Наиболее часто встречающимися символами пробела являются пробел ' ', табуляция '\t' и новая строка '\n':>>>

>>> ' \t \n '.isspace()
True
>>> '   a   '.isspace()
False

Тем не менее, есть несколько других символов ASCII, которые квалифицируются как пробелы, и если вы учитываете символы Юникода, то их еще немало:>>>

>>> '\f\u2005\r'.isspace()
True

('\f' и '\r' являются escape-последовательностями для символов ввода формы ASCII и возврата каретки; '\u2005' является escape-последовательностью для пространства Юникода Четыре на Em.)

s.istitle()

Определяет, является ли целевая строка заголовком.

s.istitle() возвращает True, если s не пусто, первый буквенный символ каждого слова в верхнем регистре, а все остальные буквенные символы в каждом слове в нижнем регистре. False В противном случае он возвращается:>>>

>>> 'This Is A Title'.istitle()
True
>>> 'This is a title'.istitle()
False
>>> 'Give Me The #$#@ Ball!'.istitle()
True

Примечание: Вот как описывается документация на Python .istitle(), на случай, если вы сочтете это более интуитивным: “Символы верхнего регистра могут следовать только за символами без кавычек, а символы нижнего регистра-только за прописными”.

s.isupper()

Определяет, являются ли буквенные символы целевой строки прописными.

s.isupper() возвращает True значение, если s оно непустое и все содержащиеся в нем буквенные символы прописные, и False в противном случае. Неалфавитные символы игнорируются:>>>

>>> 'ABC'.isupper()
True
>>> 'ABC1$D'.isupper()
True
>>> 'Abc1$D'.isupper()
False

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

Методы в этой группе изменяют или улучшают формат строки.

s.center(<width>[, <fill>])

Центрирует строку в поле.

s.center(<width>) возвращает строку, состоящую из sцентрированных в поле ширины <width>. По умолчанию заполнение состоит из символа пробела ASCII:>>>

>>> 'foo'.center(10)
'   foo    '

Если указан необязательный <fill> аргумент, он используется в качестве символа заполнения:>>>

>>> 'bar'.center(10, '-')
'---bar----'

Если s уже по крайней мере столько , сколько <width>, он возвращается без изменений:>>>

>>> 'foo'.center(2)
'foo'

s.expandtabs(tabsize=8)

Разворачивает вкладки в строке.

s.expandtabs() заменяет каждый символ табуляции ('\t') пробелами. По умолчанию пробелы заполняются при условии остановки табуляции в каждом восьмом столбце:>>>

>>> 'a\tb\tc'.expandtabs()
'a       b       c'
>>> 'aaa\tbbb\tc'.expandtabs()
'aaa     bbb     c'

tabsize является необязательным параметром ключевого слова, указывающим альтернативные столбцы табуляции:>>>

>>> 'a\tb\tc'.expandtabs(4)
'a   b   c'
>>> 'aaa\tbbb\tc'.expandtabs(tabsize=4)
'aaa bbb c'

s.ljust(<width>[, <fill>])

Слева-выравнивает строку в поле.

s.ljust(<width>) возвращает строку, состоящую из s выравнивания по левому краю в поле ширины <width>. По умолчанию заполнение состоит из символа пробела ASCII:>>>

>>> 'foo'.ljust(10)
'foo       '

Если указан необязательный <fill> аргумент, он используется в качестве символа заполнения:>>>

>>> 'foo'.ljust(10, '-')
'foo-------'

Если s уже по крайней мере столько , сколько <width>, он возвращается без изменений:>>>

>>> 'foo'.ljust(2)
'foo'

s.lstrip([<chars>])

Удаляет начальные символы из строки.

s.lstrip() возвращает копию sс любыми пробелами, удаленными с левого конца:>>>

>>> '   foo bar baz   '.lstrip()
'foo bar baz   '
>>> '\t\nfoo\t\nbar\t\nbaz'.lstrip()
'foo\t\nbar\t\nbaz'

Если указан необязательный <chars> аргумент, то это строка, указывающая набор символов, которые необходимо удалить:>>>

>>> 'http://www.programbox.ru'.lstrip('/:pth')
'www.programbox.ru'

s.replace(<old>, <new>[, <count>])

Заменяет вхождения подстроки в строке.

В Python для удаления символа из строки можно использовать .replace() метод строки Python. s.replace(<old>, <new>) возвращает копию s со всеми вхождениями подстроки<old>, замененной на <new>:>>>

>>> 'foo bar foo baz foo qux'.replace('foo', 'grault')
'grault bar grault baz grault qux'

Если указан необязательный <count> аргумент, выполняется максимум <count> замен, начиная с левого конца s:>>>

>>> 'foo bar foo baz foo qux'.replace('foo', 'grault', 2)
'grault bar grault baz foo qux'

s.rjust(<width>[, <fill>])

Справа-выравнивает строку в поле.

s.rjust(<width>) возвращает строку, состоящую из s выравнивания по правому краю в поле ширины <width>. По умолчанию заполнение состоит из символа пробела ASCII:>>>

>>> 'foo'.rjust(10)
'       foo'

Если указан необязательный <fill> аргумент, он используется в качестве символа заполнения:>>>

>>> 'foo'.rjust(10, '-')
'-------foo'

Если s уже по крайней мере столько , сколько <width>, он возвращается без изменений:>>>

>>> 'foo'.rjust(2)
'foo'

s.rstrip([<chars>])

Удаляет завершающие символы из строки.

s.rstrip() возвращает копию sс любыми пробелами, удаленными с правого конца:>>>

>>> '   foo bar baz   '.rstrip()
'   foo bar baz'
>>> 'foo\t\nbar\t\nbaz\t\n'.rstrip()
'foo\t\nbar\t\nbaz'

Если указан необязательный <chars> аргумент, то это строка, указывающая набор символов, которые необходимо удалить:>>>

>>> 'foo.$$$;'.rstrip(';$.')
'foo'

s.strip([<chars>])

Удаляет символы с левого и правого концов строки.

s.strip() по сути, это эквивалентно вызову s.lstrip() и s.rstrip() последовательности. Без <chars> аргумента он удаляет начальные и конечные пробелы:>>>

>>> s = '   foo bar baz\t\t\t'
>>> s = s.lstrip()
>>> s = s.rstrip()
>>> s
'foo bar baz'

Как и в случае с .lstrip() и .rstrip(), необязательный <chars> аргумент указывает набор символов, которые необходимо удалить:>>>

>>> 'www.programbox.ru'.strip('w.moc')
'realpython'

Примечание. Когда возвращаемое значение строкового метода является другой строкой, как это часто бывает, методы могут вызываться последовательно путем цепочки вызовов:>>>

>>> '   foo bar baz\t\t\t'.lstrip().rstrip()
'foo bar baz'
>>> '   foo bar baz\t\t\t'.strip()
'foo bar baz'

>>> 'www.programbox.ru'.lstrip('w.moc').rstrip('w.moc')
'realpython'
>>> 'www.programbox.ru'.strip('w.moc')
'realpython'

s.zfill(<width>)

Дополняет строку слева нулями.

s.zfill(<width>) возвращает копию s, дополненную '0' символами слева, в указанный <width>:>>>

>>> '42'.zfill(5)
'00042'

Если sсодержит начальный знак, он остается на левом краю результирующей строки после вставки нулей:>>>

>>> '+42'.zfill(8)
'+0000042'
>>> '-42'.zfill(8)
'-0000042'

Если s уже по крайней мере столько , сколько <width>, он возвращается без изменений:>>>

>>> '-42'.zfill(3)
'-42'

.zfill() наиболее полезно для строковых представлений чисел, но Python все равно с радостью обнулит строку, которая не является:>>>

>>> 'foo'.zfill(6)
'000foo'

Преобразование между строками и списками

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

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

Многие из этих методов возвращают либо список, либо кортеж. Это два похожих составных типа данных, которые являются прототипическими примерами итераций в Python. Они описаны в следующем уроке, так что вы скоро узнаете о них! До тех пор просто думайте о них как о последовательностях значений. Список заключен в квадратные скобки ([]), а кортеж заключен в круглые скобки (()).

С этим введением давайте взглянем на эту последнюю группу строковых методов.

s.join(<iterable>)

Объединяет строки из повторяющегося.

s.join(<iterable>) возвращает строку, полученную в результате объединения объектов, <iterable> разделенных s.

Обратите внимание , что .join() вызывается в s строке-разделителе. <iterable> также должна быть последовательность строковых объектов.

Некоторые примеры кода должны помочь прояснить ситуацию. В следующем примере разделителем s является строка', '<iterable> представляющая собой список строковых значений:>>>

>>> ', '.join(['foo', 'bar', 'baz', 'qux'])
'foo, bar, baz, qux'

В результате получается одна строка, состоящая из объектов списка, разделенных запятыми.

В следующем примере <iterable> указывается как одно строковое значение. Когда строковое значение используется в качестве итерируемого, оно интерпретируется как список отдельных символов строки:>>>

>>> list('corge')
['c', 'o', 'r', 'g', 'e']

>>> ':'.join('corge')
'c:o:r:g:e'

Таким образом, результатом ':'.join('corge') является строка, состоящая из каждого символа, 'corge' разделенного на ':'.

Этот пример не работает, потому что один из объектов в <iterable> нем не является строкой:>>>

>>> '---'.join(['foo', 23, 'bar'])
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    '---'.join(['foo', 23, 'bar'])
TypeError: sequence item 1: expected str instance, int found

Однако это можно исправить:>>>

>>> '---'.join(['foo', str(23), 'bar'])
'foo---23---bar'

Как вы скоро увидите, многие составные объекты в Python могут быть истолкованы как повторяющиеся и .join() особенно полезны для создания строк из них.

s.partition(<sep>)

Разделяет строку на основе разделителя.

s.partition(<sep>) разбивается sпри первом появлении строки <sep>. Возвращаемое значение представляет собой кортеж из трех частей, состоящий из:

  • Часть s предыдущей <sep>
  • <sep> сам
  • Часть s следующего <sep>

Вот несколько примеров .partition() в действии:>>>

>>> 'foo.bar'.partition('.')
('foo', '.', 'bar')
>>> 'foo@@bar@@baz'.partition('@@')
('foo', '@@', 'bar@@baz')

Если <sep> не найден s, возвращаемый кортеж содержит s две пустые строки, за которыми следуют две пустые строки:>>>

>>> 'foo.bar'.partition('@@')
('foo.bar', '', '')

Помните: списки и кортежи рассматриваются в следующем руководстве.

s.rpartition(<sep>)

Разделяет строку на основе разделителя.

s.rpartition(<sep>) функции точно такие s.partition(<sep>) же , за исключением того, что s разделяется при последнем вхождении <sep> вместо первого вхождения:>>>

>>> 'foo@@bar@@baz'.partition('@@')
('foo', '@@', 'bar@@baz')

>>> 'foo@@bar@@baz'.rpartition('@@')
('foo@@bar', '@@', 'baz')

s.rsplit(sep=None, maxsplit=-1)

Разбивает строку на список подстрок.

Без аргументов s.rsplit() разбивается s на подстроки, разделенные любой последовательностью пробелов, и возвращает подстроки в виде списка:>>>

>>> 'foo bar baz qux'.rsplit()
['foo', 'bar', 'baz', 'qux']
>>> 'foo\n\tbar   baz\r\fqux'.rsplit()
['foo', 'bar', 'baz', 'qux']

Если <sep> указано, оно используется в качестве разделителя для разделения:>>>

>>> 'foo.bar.baz.qux'.rsplit(sep='.')
['foo', 'bar', 'baz', 'qux']

(Если <sep> указано значение None, строка разделяется пробелами, как если <sep> бы она вообще не была указана.)

Когда <sep> явно задано в качестве разделителя, предполагается, что последовательные разделители в разделяют s пустые строки, которые будут возвращены:>>>

>>> 'foo...bar'.rsplit(sep='.')
['foo', '', '', 'bar']

Однако это не тот случай, когда <sep> он опущен. В этом случае последовательные пробелы объединяются в один разделитель, и результирующий список никогда не будет содержать пустых строк:>>>

>>> 'foo\t\t\tbar'.rsplit()
['foo', 'bar']

Если указан необязательный параметр ключевого <maxsplit> слова, выполняется максимум столько разбиений, начиная с правого конца s:>>>

>>> 'www.programbox.ru'.rsplit(sep='.', maxsplit=1)
['www.realpython', 'com']

Значение по умолчанию <maxsplit> равно -1, что означает, что должны быть выполнены все возможные разбиения—то же самое, что если <maxsplit> полностью опущено:>>>

>>> 'www.programbox.ru'.rsplit(sep='.', maxsplit=-1)
['www', 'realpython', 'com']
>>> 'www.programbox.ru'.rsplit(sep='.')
['www', 'realpython', 'com']

s.split(sep=None, maxsplit=-1)

Разбивает строку на список подстрок.

s.split() ведет себя точно так s.rsplit() же , за исключением того, что, если <maxsplit> указано, разбиения подсчитываются с левого конца s, а не с правого конца:>>>

>>> 'www.programbox.ru'.split('.', maxsplit=1)
['www', 'programbox.ru']
>>> 'www.programbox.ru'.rsplit('.', maxsplit=1)
['www.realpython', 'com']

Если <maxsplit> не указано, .split() и .rsplit() неразличимы.

s.splitlines([<keepends>])

Разрывает строку на границах строк.

s.splitlines() разбивается s на строки и возвращает их в виде списка. Любой из следующих символов или последовательностей символов считается границей линии:

Escape-последовательностьХарактер
\nНовая строка
\rВозврат кареты
\r\nВозврат Каретки + Подача Строки
\v или \x0bТаблица Строк
\f или \x0cПодача Формы
\x1cРазделитель файлов
\x1dРазделитель групп
\x1eРазделитель записей
\x85Следующая Строка (Код управления C1)
\u2028Разделитель строк Юникода
\u2029Разделитель абзацев Юникода

Вот пример использования нескольких различных разделителей строк:>>>

>>> 'foo\nbar\r\nbaz\fqux\u2028quux'.splitlines()
['foo', 'bar', 'baz', 'qux', 'quux']

Если в строке присутствуют последовательные символы границ строк, предполагается, что они разделяют пустые строки, которые появятся в списке результатов:>>>

>>> 'foo\f\f\fbar'.splitlines()
['foo', '', '', 'bar']

Если указан необязательный <keepends> аргумент и он соответствует действительности, то границы строк сохраняются в результирующих строках:>>>

>>> 'foo\nbar\nbaz\nqux'.splitlines(True)
['foo\n', 'bar\n', 'baz\n', 'qux']
>>> 'foo\nbar\nbaz\nqux'.splitlines(1)
['foo\n', 'bar\n', 'baz\n', 'qux']

bytes Объекты

bytes Объект является одним из основных встроенных типов для обработки двоичных данных. bytes Объект-это неизменяемая последовательность однобайтовых значений. Каждый элемент в bytes объекте представляет собой небольшое целое число в диапазоне 0 до 255.

Определение буквального bytes объекта

bytes Литерал определяется так же, как строковый литерал, с добавлением 'b' префикса:>>>

>>> b = b'foo bar baz'
>>> b
b'foo bar baz'
>>> type(b)
<class 'bytes'>

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

>>> b'Contains embedded "double" quotes'
b'Contains embedded "double" quotes'

>>> b"Contains embedded 'single' quotes"
b"Contains embedded 'single' quotes"

>>> b'''Contains embedded "double" and 'single' quotes'''
b'Contains embedded "double" and \'single\' quotes'

>>> b"""Contains embedded "double" and 'single' quotes"""
b'Contains embedded "double" and \'single\' quotes'

В литерале допускаются только символы ASCII bytes. Любое значение символа, превышающее 127 значение, должно быть указано с использованием соответствующей escape — последовательности:>>>

>>> b = b'foo\xddbar'
>>> b
b'foo\xddbar'
>>> b[3]
221
>>> int(0xdd)
221

'r' Префикс может использоваться в bytes литерале для отключения обработки escape-последовательностей, как в случае со строками:>>>

>>> b = rb'foo\xddbar'
>>> b
b'foo\\xddbar'
>>> b[3]
92
>>> chr(92)
'\\'

Определение bytes объекта с помощью встроенной bytes() функции

bytes() Функция также создает bytes объект. Какой тип bytes возвращаемого объекта зависит от аргумента(ов), переданного функции. Возможные формы показаны ниже.

bytes(<s>, <encoding>)

Создает bytes объект из строки.

bytes(<s>, <encoding>) преобразует строку <s> в bytes объект, используя str.encode() в соответствии с указанным <encoding>:>>>

>>> b = bytes('foo.bar', 'utf8')
>>> b
b'foo.bar'
>>> type(b)
<class 'bytes'>

Техническое примечание: В этой форме bytes() функции <encoding> требуется аргумент. “Кодировка” относится к способу преобразования символов в целочисленные значения. Значение "utf8" указывает на формат преобразования Юникода UTF-8, который представляет собой кодировку, которая может обрабатывать все возможные символы Юникода. UTF-8 также можно указать, указав"UTF8","utf-8", или "UTF-8"для <encoding>.

Дополнительную информацию смотрите в документации по Юникоду. До тех пор, пока вы имеете дело с обычными символами на основе латиницы, UTF-8 будет вам хорошо служить.

bytes(<size>)

Создает bytes объект, состоящий из байтов null (0x00).

bytes(<size>) определяет bytes указанный объект <size>, который должен быть положительным целым числом. Результирующий bytes объект инициализируется в байтах null (0x00) :>>>

>>> b = bytes(8)
>>> b
b'\x00\x00\x00\x00\x00\x00\x00\x00'
>>> type(b)
<class 'bytes'>

bytes(<iterable>)

Создает bytes объект из итерируемого.

bytes(<iterable>) определяет bytes объект из последовательности целых чисел, сгенерированных <iterable><iterable> должен быть итерируемым, который генерирует последовательность целых n чисел в диапазоне 0 ≤ n ≤ 255:>>>

>>> b = bytes([100, 102, 104, 106, 108])
>>> b
b'dfhjl'
>>> type(b)
<class 'bytes'>
>>> b[2]
104

Операции с bytes объектами

Как и строки, bytes объекты поддерживают общие операции последовательности:

  • Операторы inиnot in:
>>> b = b'abcde'

>>> b'cd' in b
True
>>> b'foo' not in b
True
  • Операторы объединения (+) и репликации (*) :
>>> b = b'abcde'

>>> b + b'fghi'
b'abcdefghi'
>>> b * 3
b'abcdeabcdeabcde'
  • Индексирование и нарезка:
>>> b = b'abcde'

>>> b[2]
99
>>> b[1:3]
b'bc'
  • Встроенные функции:
>>> len(b)
5
>>> min(b)
97
>>> max(b)
101

Многие методы, определенные для строковых объектов, действительны и для bytes объектов:>>>

>>> b = b'foo,bar,foo,baz,foo,qux'

>>> b.count(b'foo')
3

>>> b.endswith(b'qux')
True

>>> b.find(b'baz')
12

>>> b.split(sep=b',')
[b'foo', b'bar', b'foo', b'baz', b'foo', b'qux']

>>> b.center(30, b'-')
b'---foo,bar,foo,baz,foo,qux----'

Однако обратите внимание, что когда эти операторы и методы вызываются для bytes объекта, операнд и аргументы также должны быть bytes объектами:>>>

>>> b = b'foo.bar'

>>> b + '.baz'
Traceback (most recent call last):
  File "<pyshell#72>", line 1, in <module>
    b + '.baz'
TypeError: can't concat bytes to str
>>> b + b'.baz'
b'foo.bar.baz'

>>> b.split(sep='.')
Traceback (most recent call last):
  File "<pyshell#74>", line 1, in <module>
    b.split(sep='.')
TypeError: a bytes-like object is required, not 'str'
>>> b.split(sep=b'.')
[b'foo', b'bar']

Хотя bytes определение и представление объекта основаны на тексте ASCII, на самом деле оно ведет себя как неизменяемая последовательность малых целых чисел в диапазоне 0 до 255 включительно. Вот почему один элемент из bytes объекта отображается в виде целого числа:>>>

>>> b = b'foo\xddbar'
>>> b[3]
221
>>> hex(b[3])
'0xdd'
>>> min(b)
97
>>> max(b)
221

Срез отображается как bytes объект, даже если он имеет длину всего один байт:>>>

>>> b[2:3]
b'c'

Вы можете преобразовать bytes объект в список целых чисел с помощью встроенной list() функции:>>>

>>> list(b)
[97, 98, 99, 100, 101]

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

bytes.fromhex(<s>)

Возвращает bytes объект, построенный из строки шестнадцатеричных значений.

bytes.fromhex(<s>) возвращает bytes объект, полученный в результате преобразования каждой пары шестнадцатеричных цифр в <s> соответствующее значение байта. Пары шестнадцатеричных цифр в <s> необязательно могут быть разделены пробелами, которые игнорируются:>>>

>>> b = bytes.fromhex(' aa 68 4682cc ')
>>> b
b'\xaahF\x82\xcc'
>>> list(b)
[170, 104, 70, 130, 204]

Примечание: Этот метод является методом класса, а не методом объекта. Он привязан к bytes классу, а не bytes к объекту. Вы гораздо больше углубитесь в различие между классами, объектами и их соответствующими методами в следующих учебных пособиях по объектно-ориентированному программированию. На данный момент просто обратите внимание, что этот метод вызывается в bytes классе, а не в объекте b.

b.hex()

Возвращает строку шестнадцатеричного значения из bytes объекта.

b.hex() возвращает результат преобразования bytes объекта b в строку пар шестнадцатеричных цифр. То есть он делает обратное .fromhex():>>>

>>> b = bytes.fromhex(' aa 68 4682cc ')
>>> b
b'\xaahF\x82\xcc'

>>> b.hex()
'aa684682cc'
>>> type(b.hex())
<class 'str'>

Примечание: В отличие от .fromhex().hex() является методом объекта, а не методом класса. Таким образом, он вызывается для объекта bytes класса, а не для самого класса.

bytearray Объекты

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

  • В Python нет специального синтаксиса, встроенного для определения bytearray литерала, такого как 'b' префикс, который может использоваться для определения bytes объекта. bytearray Объект всегда создается с помощью bytearray() встроенной функции:
>>> ba = bytearray('foo.bar.baz', 'UTF-8')
>>> ba
bytearray(b'foo.bar.baz')

>>> bytearray(6)
bytearray(b'\x00\x00\x00\x00\x00\x00')

>>> bytearray([100, 102, 104, 106, 108])
bytearray(b'dfhjl')
  • bytearray объекты изменчивы. Вы можете изменить содержимое bytearray объекта с помощью индексирования и нарезки:
>>> ba = bytearray('foo.bar.baz', 'UTF-8')
>>> ba
bytearray(b'foo.bar.baz')

>>> ba[5] = 0xee
>>> ba
bytearray(b'foo.b\xeer.baz')

>>> ba[8:11] = b'qux'
>>> ba
bytearray(b'foo.b\xeer.qux')

bytearray Объект также может быть построен непосредственно из bytes объекта:

>>> ba = bytearray(b'foo')
>>> ba
bytearray(b'foo')

Вывод

В этом учебном пособии подробно рассматривается множество различных механизмов, которые Python предоставляет для обработки строк, включая строковые операторы, встроенные функции, индексирование, нарезку и встроенные методы. Вас также познакомили bytes с bytearray типами и.