1. Лекция 6
26 октября 2018 г.
Заметили ошибку или есть предложение? Напишите на почту: romansdidnotcrucify@gmail.com
2. Строки
2.1. Задание строк
Строки в питоне - это такие последовательности (смысл их интуитивно понятен - набор символов).
Задавать строки можно четырьмя способами:
с помощью двойных кавычек: "John";
с помощью одинарных кавычек: 'Doe' (никаких отличий от двойных кавычек);
с помощью тройных кавычек: '''John Doe can be multiline''' - позволяют задать многострочную строку (многострочный строковый литерал), а также использовать в её тексте кавычки, не прибегая к специальным символам в исходном коде;
с помощью преобразования объектов других типов: str(12).
Если вы задаёте строку с помощью двойных кавычек - можете спокойно использовать в её тексте одинарные, и наоборот. Если же вы хотите использовать в тексте строки тот же тип кавычек, которым вы обрамляете строку, вам придётся пользоваться одним из инструментов, описанных ниже.
Кстати, обратите внимание на разницу в выводе (функция print, на самом деле, выводит результат метода __str__, a интерпретатор в выводе использует __repr__):
1 >>> a = '''A multiline string
2 ... is a string that takes multiple
3 ... lines of text
4 ... '''
5 >>> a # Интерпретатор при выводе использует результат работы метода объекта __repr__ - он представляет в виде строки внутреннюю структуру объекта
6 'A multiline string\nis a string that takes multiple\nlines of text\n'
7 >>> print(a.__str__()) # __str__ задаёт строковое представление объекта - этот-то метод объекта (если он есть) и использует print
8 A multiline string
9 is a string that takes multiple
10 lines of text
11
12 >>> print(a.__repr__())
13 'A multiline string\nis a string that takes multiple\nlines of text\n'
14
2.2. Спецсимволы (управляющие символы)
При задании строки можно использовать т.н. управляющие символы - последовательности символов, которые будут интерпретироваться особым образом. В питоне такие последовательности начинаются с символа \ (backslash):
\n - перенос строки;
\t - табуляция;
\r - символ возврата каретки (подробнее здесь);
\', \" - символ - одинарная/двойная кавычка (вне зависимости от того, с помощью каких кавычек вы задаёте строковый литерал);
\\ - собственно, backslash.
1 >>> print('There will be a\nhuge fall')
2 There wiil be a
3 huge fall
4 >>> print("We need to explore\t\t\touter space")
5 We need to explore outer space
6 >>> print("I don't want to set the world on fire\rI do!!!") # Символ возврата каретки переносит наш "курсор" - то место, в которое происходит вывод - в начало строки
7 I do!!! want to set the world on fire
8 >>> print("Yep, I'm using \"double quotes\" in a double-quoted string literal")
9 Yep, I'm using "double quotes" in a double-quoted string literal
10
Полную таблицу спецсимволов можно посмотреть здесь
2.3. Коды символов
В разговоре об управляющих символах уместно будет упомянуть функции, позволяющие работать напрямую с кодами символов - ord и chr:
1 >>> ord("a") # Получить номер символа в кодировке (ord вернёт десятичное число)
2 97
3 >>> ord("abc") # Обратите внимание, что ord принимает на вход строку именно из одного символа
4 Traceback (most recent call last):
5 File "<stdin>", line 1, in <module>
6 TypeError: ord() expected a character, but string of length 3 found
7 >>> ord(a) # И именно строку
8 Traceback (most recent call last):
9 File "<stdin>", line 1, in <module>
10 TypeError: ord() expected a character, but string of length 70 found
11 >>> ord("ы") # Символы, не принадлежацие таблице ASCII, кодируются с помощью Юникода
12 1099
13 >>> chr(1099) # chr позволяет по коду символа получить сам символ (символ Юникода тоже)
14 'ы'
15 >>> hex(ord("a")) # Для примера нам потребуются шестнадцатеричные коды символов
16 '0x61'
17 >>> hex(ord("ы"))
18 '0x44b'
19 >>> print("\x61") # \xhh - управляющая последовательность, позволяющая вывести ASCII-символ по его коду
20 a
21 >>> print("\x04\x4b\x61") # Для кириллицы не подойдёт
22 Ka
23 >>> print("\u044b\x61") # Символы Юникода задаются с помощью управляющих последовательностей \u и \U (за первой следуют 4 шестнадцатеричные цифры, за второй - 8)
24 ыa
25
В питоне, начиная с третьей версии, по умолчанию строки кодируются в UTF-8 (кстати, по ссылке очень хорошо объяснена предыстория вопроса; почитайте, если плохо понимаете, что есть Юникод и с чем его едят).
2.4. Строка как последовательность
Мы уже знаем, что строка - это последовательность, и, значит, по ней можно пройтись циклом for:
Вопрос.
Что есть элемент этой последовательности?
В кортежах элементом последовательности является элемент кортежа. В строках же элемент последовательности - строка, состоящая из одного (соответствующего) символа:
1 >>> a = "Raxacoricofallapatorius"
2 >>> a[5] # Строка из одного символа
3 'o'
4 >>> a[5:9] # Новая строка из 4 символов
5 'oric'
6 >>> a[8]
7 'c'
8 >>> a[8:9]
9 'c'
10 >>> a[8] is a[8:9] # TODO: В чём принципиальное отличие строки от кортежа, кроме того, что каждый элемент строки - тоже строка? Нужно уточнить
11 True
12 >>> a[8] is 'c'
13 True
14
К слову, напомню, что строки - неизменяемый тип данных:
2.4.1. Операция in
Для строк операция in не осуществляет, как для других последовательностей, поиск первого вхождения элемента (т.е. строки из одного символа). Она осуществляет поиск подстроки в строке:
Поиск подстроки в строке в питоне имеет линейную, а не квадратичную, сложность (спасибо алгоритму Дейкстры).
2.4.2. Операция count
count осуществляет подсчёт количества вхождений подстроки в строку (что тоже является уникальным для строк поведением):
2.5. Методы строк
У строк очень много различных методов, что связано с головными болями, которые разработчики языка имели при работе с ABC/Паскалем:
1 >>> a = "asd aSDFSDv zxcdfg%^ 567567 GFHFG oikpi"
2 >>> dir(a)
3 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
4
Эти методы делятся на несколько групп.
2.5.1. Поиск
Помимо уже упомянутых in и count, следует знать также об index и find:
1 >>> a
2 'asd aSDFSDv zxcdfg%^ 567567 GFHFG oikpi'
3 >>> a.index("SDF") # Найти индекс первого вхождения подстроки в строку
4 5
5 >>> a.index("SDF!") # Если такой подстроки в строке не содержится, выбросить исключение
6 Traceback (most recent call last):
7 File "<stdin>", line 1, in <module>
8 ValueError: substring not found
9 >>> a.find("SDF") # find тоже находит первое вхождение подстроки в строку
10 5
11 >>> a.find("SDF!") # Однако в случае неуспеха не выбрасывает ошибку, а возвращает -1
12 -1
13
2.5.2. Проверки
Названия методов из этой группы начинаются на is. Сами эти методы призваны проверять различные свойства строк:
1 >>> b = "123we"
2 >>> b.isalnum() # "is alphanumeric" - содержит ли строка только буквы и цифры
3 True
4 >>> b = "123we!"
5 >>> b.isalnum()
6 False
7 >>> b = "123we_" # К слову, нижнее подчёркивание буквой не считается
8 >>> b.isalnum()
9 False
10 >>> b = "йцукен" # Буквами считаются и буквы в Юникоде
11 >>> b.isalnum()
12 True
13 >>> "1234".isdigit() # isdecimal, isdigit, isnumeric - проверка, состоит ли строка из цифр (с некоторыми тонкостями)
14 True
15 >>> "1234".isdecimal()
16 True
17 >>> "1234F".isdecimal()
18 False
19 >>> "1234F".isdigit()
20 False
21 >>> b = "123qwe"
22 >>> b.isidentifier() # Проверка, может ли строка быть идентификатором (именем объекта), т.е. является ли она последовательностью букв, цифр и _, начинающейся не с цифры
23 False
24 >>> b = "_123qwe"
25 >>> b.isidentifier()
26 True
27 >>> "asd".islower() # islower - состоит ли строка только из строчных букв
28 True
29 >>> "aSd".islower()
30 False
31 >>> "ASD".isupper() # isupper - состоит ли строка только из прописных букв
32 True
33 >>> "AsD".isupper()
34 False
35 >>> "word".isprintable() # isprintable - состоит ли строка только из печатных символов
36 True
37 >>> "word\n".isprintable()
38 False
39 >>> "\n\t \t\n".isspace() # isspace - состоит ли строка только из пробельных символов
40 True
41 >>> "\n\t ! \t\n".isspace()
42 False
43 >>> "Avalidtitle".istitle() # istitle - проверяет, состоит ли строка только из слов, разделённых пробелами, состоящих только из букв и начинающихся с прописной буквы каждое
44 True
45 >>> "A nonvalid title".istitle()
46 False
47 >>> "A_non-valid_title".istitle()
48 False
49 >>> "Anon-validtitle".istitle()
50 False
51 >>> "Anon123alidtitle".istitle()
52 False
53 >>> "ANonValidTitle".istitle()
54 False
55 >>> "A Valid Title".istitle()
56 True
57
Про разницу между isdecimal, isdigit и isnumeric можно почитать здесь.
2.5.3. Методы форматирования
1 >>> s = "qWe"
2 >>> s.lower() # lower - преобразование всех букв в строчные
3 'qwe'
4 >>> s.upper() # upper - преобразование всех букв в прописные
5 'QWE'
6 >>> a.capitalize() # capitalize - преобразование первой буквы в прописную
7 'Asd asdfsdv zxcdfg%^ 567567 gfhfg oikpi'
8 >>> a.title() # title - преобразование первых букв всех слов в прописные
9 'Asd Asdfsdv Zxcdfg%^ 567567 Gfhfg Oikpi'
10 >>> s.swapcase() # swapcase - сменить регистр всех букв в строке
11 'QwE'
12 >>> a.casefold() # casefold - привести строку к такому виду, в котором её возможно сравнивать (>, <) с другими строками вне зависимости от регистра букв
13 'asd asdfsdv zxcdfg%^ 567567 gfhfg oikpi'
14
2.5.4. replace
Гораздо более интересный метод - replace. Он позволяет заменить вхождения подстроки на заданную строку:
2.5.5. Работа с пробельными символами
Как убрать лишние пробелы? Методами lstrip, rstrip и strip:
Кроме того, есть метод expandtabs, являющийся наследием второго питона и позволяющий раскрыть символы табуляции в строке по определённым правилам.
2.5.6. zfill
Метод zfill позволяет дополнить строку, состоящую из цифр, нулями слева, чтобы получить строку длины не меньше указанной:
2.6. split и join
Самые интересные и полезные методы работы со строками я даже выделил в отдельный раздел.
2.6.1. split
Метод split позволяет разбить строку на части по какому-либо символу (по умолчанию - по целым подпоследовательностям, состоящим из пробельных символов). При этом результатом его работы будет список подстрок исходной строки:
1 >>> a
2 'asd aSDFSDv zxcdfg%^ 567567 GFHFG oikpi'
3 >>> a.split() # Разбить строку на подстроки по пробельным символам (последовательность пробельных символов как бы считается за один символ)
4 ['asd', 'aSDFSDv', 'zxcdfg%^', '567567', 'GFHFG', 'oikpi']
5 >>> nn = "123 32 2134 346 657 56 1234 436" # Это очень удобно для анализа ввода с клавиатуры
6 >>> [int(n) for n in nn.split()]
7 [123, 32, 2134, 346, 657, 56, 1234, 436]
8 >>> nn.split("3") # Можно и указать подстроку, по которой выполнять разбиение
9 ['12', ' ', '2 21', '4 ', '46 657 56 12', '4 4', '6']
10 >>> a = "a,,d,r,,,e,,r" # Если вы указываете подстроку, по которой разбивать данную, вы можете получить в массиве и пустые строки
11 >>> a.split(",")
12 ['a', '', 'd', 'r', '', '', 'e', '', 'r']
13 >>> a.split(",,") # Эта подстрока, конечно, не обязана состоять из одного символа
14 ['a', 'd,r', ',e', 'r']
15
Метод split очень, ОЧЕНЬ часто используется при анализе входных данных с клавиатуры.
Частный случай работы метода split, с некоторыми нюансами (например, независимость от используемого в ос символа новой строки), представляет метод splitlines:
2.6.2. join
Можно выполнить и обратную операцию - объединить несколько строк в одну:
1 >>> sn = nn.split()
2 >>> "__".join(sn) # Таким образом можно задать тот разделитель, которым нужно соединять строки
3 '123__32__2134__346__657__56__1234__436'
4 >>> "".join(sn) # Т.к. join - метод строки, то, даже если нам не нужен разделитель, хотя бы пустую строку указать придётся
5 '123322134346657561234436'
6
Может возникнуть вопрос: зачем это делать с помощью отдельного метода, если есть операция конкатенации +?
Эффективность. Если только вы хотите объединить не две строки, а больше, попытка сделать это через конкатенацию приведёт к тому, что на каждую конкатенацию двух строк интерпретатор создаст отдельный объект (даже если записать всё выражение в виде "a + b + c + d + ...").
В CPython эту проблему обходят с помощью хака, но вообще полагаться на эффективную реализацию конкатенации строк не стоит (но и ради сложения двух строк использовать join смысла нет).
В интернетах если не продолжаются до сих пор, то, по крайней мере, легко находятся старые холивары на тему того, какой метод эффективнее, и не всегда наиболее оцененный комментарий - верный. Так что будьте аккуратны, сверяйтесь с несколькими источниками и не забывайте проверять даты публикаций.
2.7. Форматирование строк
Кстати, посмотрите, что мы уже знаем про форматирование строк.
2.7.1. Модификатор r
Если вы не хотите, чтобы управляющие последовательности в вашей строке обрабатывались (скажем, вы хотите напечатать \n именно как два символа, а не как перенос строки), укажите перед открывающей кавычкой модификатор r (от raw - сырой, необработанный):
С модификатором r, впрочем, есть некоторые тонкости.
2.7.2. Форматные строки
В питоне версии 3.6 (который не так уж давно появился) был добавлен такой весьма удобный инструмент, как форматные строки.
Идея форматных строк восходит к концепции шаблонов и похожа на то, как форматируются строки в C (в питоне C-подобный язык форматирования тоже поддерживается, но он считается устаревшим и потому не главным).
Главным считается другой форматный язык, более мощный. Для его использования при интерпретации строки перед ней нужно указать модификатор f.
Непонятно, с чего здесь начать, поэтому покажу всё на примерах:
1 >>> f"____===={10:8}====____" # Помимо текста снаружи них, в фигурных скобках указывается то выражение, которое должно быть отформатировано; через двоеточие после него можно указать минимальное количество символов, которое должна занимать получаемая подстрока
2 '____==== 10====____'
3 >>> f"____===={10:08}====____" # Можно не только указать минимальную ширину подстроки, но и заполнитель, который будет использован
4 '____====00000010====____'
5 >>> f"____===={10:<8}====____" # Можно выровнять подстроку по левому краю
6 '____====10 ====____'
7 >>> f"____===={10:^8}====____" # А можно и по центру (по правому краю она выравнивается по умолчанию)
8 '____==== 10 ====____'
9 >>> f"____===={10.123456789192:^8}====____" # Обратите внимание, впрочем, что здесь указывается именно минимальная, но не максимальная допустимая ширина подстроки
10 '____====10.123456789192====____'
11 >>> f"____===={10.123456789192:22}====____"
12 '____==== 10.123456789192====____'
13 >>> f"____===={10.123456789192:22.20}====____" # Для чисел можно указать, сколько знаков после запятой должно быть выведено
14 '____==== 10.123456789191999761====____'
15 >>> n = 100500 # Хуже того, в фигурных скобках могут фигурировать объявленные ранее переменные
16 >>> f"____{n}____{n:8}____{a}"
17 '____100500____ 100500____\\n\\n\\n\\n'
18 >>> f"____{n}____{n // 3 :8}____{a}" # И целые выражения; т.е. сначала для каждого форматируемого фрагмента выполняется eval, и только потом происходит форматирование
19 '____100500____ 33500____\\n\\n\\n\\n'
20 >>> f"____{n}____{nnn // 3 :8}____{a}" # Следующие из этого ошибки и потенциальные угрозы - такие же, как у eval
21 Traceback (most recent call last):
22 File "<stdin>", line 1, in <module>
23 NameError: name 'nnn' is not defined
Повторюсь, что, т.к. при обработке форматных строк выполняется, по сути, eval, применять их в продакшен-коде не рекомендуется точно так же и по тем же причинам, что и eval.
2.7.3. Строковый метод format
Форматные строки появились только в Python 3.6, а в предыдущих версиях для форматирования строк можно было пользоваться только таким инструментом, как строковый метод format.
Работает это так:
1 >>> "{1}, {0}, {1}, {2}".format(10,20,30) # В фигурных скобках указывается индекс параметра, переданного в format, который нужно подставить в данное место строки
2 '20, 10, 20, 30'
3 >>> "qqwe {} sdfsdf {}".format(10,20) # Можно оставить фигурные скобки пустыми, и тогда выбор параметра будет осуществлён автоматически (они будут взяты просто по порядку)
4 'qqwe 10 sdfsdf 20'
5 >>> "qqwe {1} sdfsdf {}".format(10,20,30) # Единственное, смешивать эти два подхода нельзя
6 Traceback (most recent call last):
7 File "<stdin>", line 1, in <module>
8 ValueError: cannot switch from manual field specification to automatic field numbering
9 >>> "qqwe {} sdfsdf {2}".format(10,20,30)
10 Traceback (most recent call last):
11 File "<stdin>", line 1, in <module>
12 ValueError: cannot switch from automatic field numbering to manual field specification
13 >>> "qqwe {:8} sdfsdf {}".format(10,20) # Для форматируемого параметра можно указать дополнительные свойства, например, опять-таки, минимальную ширину занимаемой им подтроки
14 'qqwe 10 sdfsdf 20'
15
Метод format, в отличие от форматных строк, безопасен: никакого eval при форматировании не выполняется, всё, что должно быть вычислено, вычисляется ещё на этапе передачи параметров в метод.
Для наших домашних заданий, по крайней мере, этого метода будет более чем достаточно; к тому же, т.к. форматные строки появились сравнительно недавно, при чтении чужого кода вы много где встретите именно format.
Тем не менее, на сервере ejudge на данный момент уже установлен Python 3.7, так что у вас должны работать оба способа форматирования строк.
2.8. Байтовые строки
2.8.1. Что такое строка с точки зрения питона
Строка в питоне - это последовательность символов.
Если вы заметили, я несколько раз за сегодня оговаривался и вместо "символы" говорил "буквы". Это было неспроста: символы в питоне - это не то же, что символ в C.
Символ в питоне - это то, что выводится на экран.
Потому даже те символы, которые принадлежат ASCII и должны бы кодироваться одним байтом, в зависимости от контекста могут кодироваться бОльшим числом байт:
1 >>> import sys # С помощью специального метода посмотрим, сколько байт занимают наши строки
2 >>> sys.getsizeof('12345') # Кроме собственно символов, в строку входит также служебная информация
3 54
4 >>> sys.getsizeof('123456') # Добавим ASCII-символ (пока что вся наша строка состоит только из них)
5 55
6 >>> sys.getsizeof('123456w') # При этом размер, как и ожидалось, увеличивается на 1
7 56
8 >>> sys.getsizeof('123456wы') # А вот при добавлении руской буквы получаем значительное увеличение размера
9 90
10 >>> a = "waffle345вафля" # Почему? Потому что теперь нужно всю строку хранить, выделяя на каждый символ по 2 байта
11 >>> a[0] # Такое поведение позволяет при обращении со строками не думать о том, какой кодировке на самом деле принадлежит символ
12 'w'
13 >>> a[10] # Кроме того, оно позволяет обеспечить совместимость с самыми разными кодировками, которые могут использоваться в операционной системе (в одной только windows, в зависимости от ситуации, используется не менее 4 различных кодировок)
14 'а'
15
Чтение из файла, и даже чтение с клавиатуры - в общем-то, непростые операции. Так, например, в линуксе при чтении с клавиатуры ASCII-символы кодируются одним байтом, а символы Юникода могут кодироваться некоторые двумя, а некоторые - четырьмя байтами. А в питоне нужно выбрать единую кодировку для всей считываемой строки.
2.8.2. bytes
В питоне есть специальный тип данных - байтовая строка (он же - байтовый массив). Он чем-то похож на массив символов в C:
1 >>> b = b"qwerqwer" # Обозначается он как строковый литерал с модификатором `b`
2 >>> type(b)
3 <class 'bytes'>
4 >>> a = 'asdfasdf' # Для сравнения - строка
5 >>> type(a)
6 <class 'str'>
7 >>> b # Когда символов несколько - bytes ведёт себя как строка
8 b'qwerqwer'
9 >>> b * 3
10 b'qwerqwerqwerqwerqwerqwer'
11 >>> b + b'ret'
12 b'qwerqwerret'
13 >>> b[0] # Но вот при индексации мы получим не сами символы (либо части символов, если речь о символах Юникода), а их числовые значения
14 113
15 >>> b[1]
16 119
17 >>> b[1] = 6 # Тип bytes - неизменяемый, прямо как строка
18 Traceback (most recent call last):
19 File "<stdin>", line 1, in <module>
20 TypeError: 'bytes' object does not support item assignment
Зачем нужен тип bytes? Для чтения бинарных файлов.
Что произойдёт, если загнать в bytes русские буквы?
1 >>> ф = '-абвг' # К слову, идентификаторы не обязаны состоять именно из ascii-символов
2 >>> a = '-абвг' # Но мы изгаляться всё же не будем
3 >>> bytes(a) # Если строка содержит не-ASCII-символы, для преобразования её в bytes требуется указать кодировку, с помощью которой будет произведено кодирование
4 Traceback (most recent call last):
5 File "<stdin>", line 1, in <module>
6 TypeError: string argument without an encoding
7 >>> bytes(a, 'UTF-8') # При этом в различных кодировках получим и различное байтовое представление: в UTF-8 на каждый символ в нашем примере будет отведено по 2 байта
8 b'-\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3'
9 >>> bytes(a, 'KOI8-R') # А в некоторых других кодировках - по одному
10 b'-\xc1\xc2\xd7\xc7'
11 >>> bytes(a, 'CP1251')
12 b'-\xe0\xe1\xe2\xe3'
13
Олдфаги помнят (а дело было лет 10-20 назад) такое слово, как "бнопня". Оно было широко известно в среде системных администраторов:
1 >>> a = "Вопрос" # Присылают вам письмо с вопросом, но не указывают, нарушая правила, кодировку, которую используют
2 >>> a.encode("cp1251") # Допустим, пользователь использовал кодировку cp1251
3 b'\xc2\xee\xef\xf0\xee\xf1'
4 >>> a.encode("cp1251").decode("koi8-r") # А вы, как администратор на линуксе, со своей KOI8-кодировкой вместо "Вопрос" увидите:
5 'бНОПНЯ'
6
Кроме сказанного, данные типа bytes поддерживают все строковые методы:
1 >>> dir(bytes)
2 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'center', 'count', 'decode', 'endswith', 'expandtabs', 'find', 'fromhex', 'hex', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
3
Есть даже дополнительный метод hex, позволяющий быстро перевести байтовую строку в строку из кодов её символов:
2.8.3. bytearray
Bytearray - это bytes, но изменяемый.
1 >>> b = bytearray("QWERTY") # При создании bytearray из строки тоже нужно указывать кодировку
2 Traceback (most recent call last):
3 File "<stdin>", line 1, in <module>
4 TypeError: string argument without an encoding
5 >>> b = bytearray("QWERTY", "UTF-8")
6 >>> b
7 bytearray(b'QWERTY')
8 >>> print(b)
9 bytearray(b'QWERTY')
10 >>> b[0] # При индексации вы так же будете получать численное значение символа, а не сам символ
11 81
12 >>> b[1]
13 87
14 >>> b[4] = 32 # Вы можете изменять bytearray - однако помните, что вы работаете с численными значениями
15 >>> b
16 bytearray(b'QWER Y')
17 >>> b[4] = '!' # Присвоить напрямую желаемый символ не получится
18 Traceback (most recent call last):
19 File "<stdin>", line 1, in <module>
20 TypeError: an integer is required
21 >>> dir(bytearray) # У bytearray тоже есть все строковые (и не только) методы
22 ['__add__', '__alloc__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'capitalize', 'center', 'clear', 'copy', 'count', 'decode', 'endswith', 'expandtabs', 'extend', 'find', 'fromhex', 'hex', 'index', 'insert', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'pop', 'remove', 'replace', 'reverse', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
23
Таким образом, с bytearray вы можете работать:
- как со строками;
- как со списками;
- как с байтовыми строками.
Единственный недостаток bytearray, вытекающий из свойств кодировок - напрямую, скажем, с русскими символами вы работать не можете.