====== Числа, Cтроки, RegExp ======
===== Числа =====
Операции над числами разных типов возвращают **число в более сложном типе**\\
Числа можно записывать в **двоичном**, **восьмеричном** и **шестнадцатеричном** виде, они **автоматом будут приведены** к десятичной форме\\
* **Двоичное** - начинаются с символов **0b (0B)**
* **Восьмеричное** - начинаются с символов **0о (0О)**
* **Шестнадцатеричное** - начинаются с символов **0x (0X)**
* **Вещественное** - содержит точку либо символ **Е (е)**, есть модуль/функция **Decimal**, для фиксированной точности
* **Дробное** - модуль/функция **Fraction**
* **Комплексное** - <Вещественная часть> + <Мнимая>J (j)
0b101101 # 45
0o12 # 10
0xA # 10
.14 # 0.14
Fraction(1,2); Fraction("0.5") # дробь, одна вторая
# в python 3.6, для удобства, можно добавлять подчеркивание
0b1111_1111 # 255
==== Функции и методы ====
* **int(), float(), bin(), oct(), hex()** - преобразование (целое, вещественное, двоичное, восьмеричное, шестнадцатеричное с-но)
* **round(<Число>,<Кол-во знаков после запятой>=0)** - округление
* **abs()** - абсолютное число
* **pow(<Число>, <Степень>, <Делитель>=)** - возведение в степень
* **max(), min()** - принимает список чисел через запятую
* **sum(<Последовательность>,<Нач значение>=0)** - принимает списки, кортежи и т.д.
* **divmod(x,y)** - возвращает кортеж из двух значений
Float так же поддерживает
* **is_integer()** - если нет дробной части
* **as_integer_ration()** - вернет два числа, целую и дробную части
==== Модуль math ====
Содержит константы типа **pi**, **e** и т.д.\\
Функции типа **sin(), cos(), tan(), exp(), log(), pow(), fmod(), fsum(), factorials**и т.д.\\
==== Модуль random ====
* **random()** - псевдослучайное число от 0.0 до 1.0
* **seed(<Параметр>, <версия>=2)** - настраивает генератор на новую последовательность
* **choice(<Последовательность>)** - случайный выбор из заданной последовательности (строка, список, кортеж и т.д.)
* **suffle()** - перемешивает заданную последовательность, сохраняя изменения в объекте
* **uniform(<Начало>, <Конец>)/randint(<Начало>, <Конец>)** - псевдослучайное вещественное/целое, в диапазоне
* **randrange(<Начало>=0, <Конец>, <Шаг>=1)** - из диапазона, тут же его генерирует
random.random()
random.seed(10)
random.choice("String")
random.randrange(100,2)
===== Строки и двоичные данные =====
Длинна строки ограничивается лишь объемом ОЗУ\\
Как и все последовательности поддерживает обращение по индексу, конкатенацию, срез, проверка на вхождение и т.д.\\
**Неизменяемый** тип данных т.е. методы **возвращают новую строку**, а не сам элемент, который можно изменить.\\
**Нулевой символ не является концом строки**\\
* **str** - Unicode строка, при выводе можно указывать кодировку
* **bytes** - неизменяемая последовательность байт, элементы хранят значения 0..255, поддерживает большинство методов строк, доступ по индексу возвращает целое число, а не символ. Может содержать как однобайтовые так и многобайтовые символы
* **bytearray** - изменяемая последовательность байт
==== Создание строки ====
Если преобразовывать из bytes/bytearray, то необходимо указывать кодировку в функции **str()**, так же, она принимает параметры исключений, третьим параметром\\
**Разницы между двойными кавычками и апострофами нет**\\
Спец символы экранируются слешем либо символом **r** перед строкой\\
**Тройные кавычки** (апострофы) сохраняют все форматирование, добавляются в документацию (func.__doc__), печатают все спец символы\\
**Конкатенация** может происходить слешем, плюсом, внутри скобок\\
==== Спец символы ====
Типа: n,r,t,v,a,b,f - перевод строки/каретки, табуляция/вертикальная, звонок/забой оО ?, перевод формата и т.д.\\
Пишутся после слеша с-но\\
==== Операции над строками ====
Обращение по индексу, если индекс отсутствует - исключение **IndexError**\\
В индексе можно указать **отрицательное значение**, тогда отсчет **идет с конца** (значение отнимается от длинны строки)\\
Полезен метод **извлечения среза**, все параметры необязательны, возвращается копия строки\\
[<Начало>:<Конец>:<Шаг>]
s= Python
s[:] # вся строка
s[::-1] # в обратном порядке
"J"+ s[1:] # замена первого символа
s[:-1] # удалить последний символ
s[0:1]; s[-1:] # получить первый (последний)
s[2:5] # часть строки
==== Форматирование строк ====
<Строка специального формата> % <Значение>
%[(<Ключ>)] [<Флаг>] [<Ширина>] [.<Точность>] <Тип преобразования>
"%s - %s - %s" % (10,20,30) # '10 - 20 - 30'
# <Ключ> - ключ словаря, в этом случае должен быть указан словарь
"%(name)s - %(year)s" % {"year": 1978, "name": "Nil"}
# <Флаг> - флаг преобразования (пробелы, нули, системы счисления)
# <Ширина> - мин ширина поля
=== Метод format() ===
В последующих версиях python знак **%** перестанет использоваться, рекомендуется использовать этот метод
<Строка> = <Строка спец формата>.format(*args, **kwargs)
{[<Поле>] [!<Функция>] [:<Формат>]}
"{0} - {1} - {2}".format(10, 12.3, "String") # '10 - 12.3 String'
==== Форматируемые строки ====
В python 3.6 есть альтернатива методу **format()**, т.н. "Форматируемая строка", она обязательно предваряется символом **f (F)**, и вставляет переменные у казанные места.. типа того
{[<Переменная>] [!<Функция>] [:<Формат>]}
a= 10; b= 12.3; s= "string"
f"{a} - {b} - {s}"
# Еще вариант вставки переменных в строку
print("{0} - {1}".format(1, 2))
==== Функции и методы строк ====
* **strip()** - удаляет указанные символы в начале и конце строки (если не указано то пробелы удаляет)
* **l[r]strip()** - тоже самое только вначале (в конце) строки
* **split(<Разделитель>=пробел, <Лимит>= )** - разбивает на подстроки
* **rsplit()** - справа на лево
* **splitlines(- не включать разделить в результат)** - разбивает по строкам (символ переноса строки)
* **join()** - собирает строку "<строка> = <разделитель>.join(<последовательность>)" - :!: п*дарастическая ф-я, непонятки с кодировкой после нее
" => ".join(["one", "two", "three"]) # 'one => two => three'
==== Локаль ====
**locate(<категория>, <локаль>= )**\\
Модуль **locale**, устанавливать несколько раз.\\
Установить можно командой **locate.setlocate(<Категория>)**, получить текущую **locate.getlocate(<Категория>)**, получить настройки локали можно **locate.localeconv()**\\
* **locate.LC_ALL** - для всех режимов
* **locate.LC_COLLATE** - для сравнения строк
* **locate.LC_CTYPE** - для перевода регистра
* **locate.LC_MONETARY** - для денежных единиц
* **locate.LC_NUMERIC** - для чисел
* **locate.LC_TIME** - для даты/время
==== Регистр символов ====
**upper(), lower(), swapcase(), capitalize(), title(), casefold()**- верхний/нижний/противоположный регистры, первая буква заглавная, тоже но для каждого слова, заменяет расширенные символы буквами, полезно при сравнении строк.\\
==== Функции и методы символов ====
**chr(), ord()**- возвращает символ указанного кода, и код указанного символа\\
==== Поиск и замена ====
* **find()** - возвращает номер позиции с которой начинается подстрока или -1 если ее нет, **чувствителен к регистру**. <строка>.find(<подстрока>, <начало>=, <конец>= ), если начало и конец указаны, поиск производится в срезе
* **index()** - аналогично, но вызовет исключение если подстроки нет
* **rfind()/rindex()** - аналогично но возвращает номер последнего вхождения
* **count()** - кол-во вхождений
* **startswith()/endswith()** - начинается (заканчивается) ли строка с указанной подстроки
* **replace()** - возвращает новую строку. <строка>.replace(<подстрока>, <новая подстрока>, <мах кол-во замены>= )
* **translate(<таблица символов>)** - в аргументе принимает словарь, собсна заменяет все указанные символы соответствующими, "None"- удаляет. В ключе словаря должен быть указано Unicode номер символа, с этим может помочь метод **maketrans(dict)**. Для удаления можно указать целую строку символов, третьим параметром
==== Проверка типа содержимого строки ====
Есть рад функций типа **isalnum()**, **isalpha()**, **isdigit()**, **isdecimal()**, **isnumeric()**, **isupper()**, **istitle()** и т.д., для проверки содержимого\\
==== bytes ====
Хранит в себе неизменяемую последовательность байт, от 0..255, можно хранить бинарные данные, поддерживает множество строковых методов\\
**bytearray**- впринципе тоже самое, но последовательность изменяемая\\
==== Преобразование ====
Преобразовать объект в последовательность байтов (т.е. выполнить сериализацию/десериализацию) можно с помощью **модуля pickle**\\
* **dump(<Объект>, <протокол>=, =True)** - возвращает последовательность байт, в соответствии с протоколом
* **load(<последовательность байт>, =True, =ASCII, )** - обратное д-е
==== Шифрование ====
Модуль **hashlib**\\
Функции типа **md5()**, **sha1,224,256,384()**, в 3.6 появились еще **sha3_224,256,512()** и т.д.
===== Регулярные выражения =====
**import re**\\
[[https://python.ivan-shamaev.ru/python-3-regular-expressions-regex-match-group-string|Дока]]\\
==== Синтаксис ====
Шаблон нужно компилировать ф-ей **compile()**\\
:!: Символ **r** перед строкой позволяет не экранировать спец символы\\
<Шаблон>= re.compile(<Рег выражение>, <Модификатор>=)
p= re.compile(r"^[а-я]+$")
if p.search("Input string"):
# Либо
if re.search("^[а-я]+$", "Input string"):
Модификаторы:
* **I (IGNORECASE)** - регистр
* **M (MULTILINE)** - текст с подстроками, символы ^ и $ относятся к подстрокам
* **S (DOTALL)** - если указать, то символ точка соответсвует переводу стоки.. оО
* **X (VERBOSE)** - пробелы и перевод строки игнорируется
Экранирование слешем (\) или в квадратных скобках
re.compile(r"^[0-3][0-9]\.[01][0-9]\.[12]$")
re.compile(r"^[0-3][0-9][.][01][0-9][.][12]$")
Символы ^ и $ зависят от модификаторов (M или S), \A и \Z- аналогичные, но не зависят от модификаторов\\
p= re.compile(r"^.+$") Точка не соответствует \n
p.findall("Str1\nStr2\nStr3") # Ничего не найдено
p= re.compile(r"^.+$", re.S) # Теперь соответствует
p.findall("Str1\nStr2\nStr3") # Найдена все строка, целиком
p= re.compile(r"^.+$", re.M) # Многострочный режим
p.findall("Str1\nStr2\nStr3") # list из трех подстрок
p= re.compile(r"Красн((ая)|(ое))")
p.search("Красное")
# Позиция для поиска
p= re.compile(r"\bPython\b")
p.search("Python")
p= re.compile(r"\Bthon\b")
p.search("Python")
Вместо символов можно использовать классы:
* **\d** - цифры
* **\w** - цифры и буква
* **\s** - любой пробельный символ
* **\D, \W, \S** - тоже самое, ток отрицание
* **\b** - начало слова
* **\B** - не начало слова
Число вхождений, типа:
* **{n}, {n,}, {n,m}** - ровно **n**, **n** и более, от **n** до **m**
* ***** - ноль или более
* **+** - одно или более
* **?** - ни одного
Ищется самая длинная строка, пропуская более короткие соответствия, чтобы ограничить, нужно указать ?\\
Получить содержимое тегов '
' вместе с тегами:
s= '
Text1Text2
Text3'
p= re.compile(r"
.*", re.S)
p.findall(s)
>> ['
Text1Text2
Text3'] # Получили всю строку
p= re.compile(r"
.*?", re.S) # Ограничили "Жадность"
p.findall(s)
>> ['
Text1', '
Text3']
p= re.compile(r"
(.*?)", re.S) # Добавили скобки
p.findall(s)
>> ['Text1', 'Text3'] # Результат без тегов !!!
Скобки **группируют фрагменты**, чтобы отбросить из результата сами фрагменты, нужно указать **?:** внутри скобок\\
Например (?:tx) найдет и "Text" и "tx", чтобы второго не было, нужно указать **?:**\\
К найденному фрагменту можно обратится, по порядковому номеру или по имени, номера есть по умолчанию- **\№**\\
Например получим текст между одинаковыми тегами:
s= 'Text1 Text4 Text2 Text3'
p= re.compile(r"<([a-z]+)>(.*?)\1>", re.S | re.I)
p.findall(s)
>> [('b', 'Text1'), ('I', 'Text2'), ('b', 'Text3')]
# ?P - для задания имени фрагменту
s= 'eed 34 dc 3455'
p= re.compile(r"(?P[0-9]+) (?P[a-z]+)", re.I)
p.search(s)
p.group('digit')
>> '34' # Пока точно не уверен на чет результата, нужно больше углубления
==== Поиск первого совпадения ====
Для этого есть следующе методы (и функции их аналоги):
* **match()** - соответствие с началом строки
* **search()** - соответствие с любой частью строки
* **fullmatch()** - соответствие со всей строкой
Объект **Match** содержит следующие свойства и методы:
* **re** - ссылка на скомпилированный шаблон, в ней есть следующие атрибуты:
* **groups (groupindex)** - кол-во групп в шаблоне (перечисление в словаре)
* **pattern** - строка с рег выражением
* **flags** - комбинация флагов
* **string** - строка .. оО
* **pos (endpos)** - начальная/конечная позиции
* **lastindex (lastgroup)** - пар-ры последней группы
* **group (groups, groupdict)** - фрагменты, соответствующие шаблону
* **start (end)** - начало/окончание фрагмента
* **span** - кортеж с начальным и конечным индексами фрагмента
* **expand** - замена в строке
==== Поиск всех совпадений ====
Это так же функции и методы:
* **findall()** - возвращает список (строк или кортежей), ищет все соответствия
* **finditer()** - возвращает итератор, на каждой итерации возвращает **Match**
==== Замена в строке ====
Метод **sub()** ищет все совпадения и заменяет указанным значением\\
sub[<Новый фрагмент или ссылка на функцию>, <Строка для замены>, <Мах кол-во замен>=]
Внутри нового фрагмента можно использовать **обратные ссылки** типа (\номер элемента \g название группы \g номер группы)\\
# Поменяем два тега местами
p= re.compile(r"<(?P[a-z]+)><(?P[a-z]+)>")
print(p.sub(r"<\2><\1>", "
"))
print(p.sub(r"<\g<2>><\g<1>>", "
"))
print(p.sub(r"<\g><\g>", "
"))
# Функция для замены
def repl(match):
x= int(match.group(0))
x += 10
return "{0}".format(x)
p= re.compile(r"[0-9]+")
print(p.sub(repl, "2008, 2009, 2010, 2011"))
==== Прочие функции и методы ====
* **split()** - разбивка строки
* **escape()** - экранирует все символы (re.escape(r"[]{}."))
* **purge()** - очистка кэша рег выражений