1. Лекция 6

26 октября 2018 г.

Заметили ошибку или есть предложение? Напишите на почту: romansdidnotcrucify@gmail.com

/!\ ACHTUNG! WORK IN PROGRESS! /!\

Данная страница ещё не закончена и находится в процессе дополнения и переработки. Почитать уже можно, но не забудьте потом заглянуть, когда будет полная версия.

2. Строки

2.1. Задание строк

Строки в питоне - это такие последовательности (смысл их интуитивно понятен - набор символов).

Задавать строки можно четырьмя способами:

  1. с помощью двойных кавычек: "John";

  2. с помощью одинарных кавычек: 'Doe' (никаких отличий от двойных кавычек);

  3. с помощью тройных кавычек: '''John Doe can be multiline''' - позволяют задать многострочную строку (многострочный строковый литерал), а также использовать в её тексте кавычки, не прибегая к специальным символам в исходном коде;

  4. с помощью преобразования объектов других типов: 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):

  1. \n - перенос строки;

  2. \t - табуляция;

  3. \r - символ возврата каретки (подробнее здесь);

  4. \', \" - символ - одинарная/двойная кавычка (вне зависимости от того, с помощью каких кавычек вы задаёте строковый литерал).

   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 >>> for i in "QWERTY":
   2 ...     print(i)
   3 ...
   4 Q
   5 W
   6 E
   7 R
   8 T
   9 Y
  10 

Вопрос.

В кортежах элементом последовательности является элемент кортежа. В строках же элемент последовательности - строка, состоящая из одного (соответствующего) символа:

   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 

К слову, напомню, что строки - неизменяемый тип данных:

   1 >>> a[6] = "v"
   2 Traceback (most recent call last):
   3   File "<stdin>", line 1, in <module>
   4 TypeError: 'str' object does not support item assignment

2.4.1. Операция in

Для строк операция in не осуществляет, как для других последовательностей, поиск первого вхождения элемента (т.е. строки из одного символа). Она осуществляет поиск подстроки в строке:

   1 >>> a
   2 'Raxacoricofallapatorius'
   3 >>> "o" in a    # Это мы уже видели на примере других последовательностей
   4 True
   5 >>> "fall" in a    # А вот это - нечто новое
   6 True
   7 >>> "gravity fall" in a
   8 False
   9 

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

2.4.2. Операция count

count осуществляет подсчёт количества вхождений подстроки в строку (что тоже является уникальным для строк поведением):

   1 >>> a.count("co")    # Потому что вместо подсчёта вхождений одного элемента последовательности мы считаем количество вхождений целой подпоследовательности
   2 2
   3 

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()    # istile - очень странный метод, проверяющий, состоит ли строка только из букв и является ли первая из них прописной, а остальные - строчными
  44 True
  45 >>> "A non-valid 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 

Про разницу между isdecimal, isdigit и isnumeric можно почитать здесь.

2.5.3. Методы форматирования