Обработка данных. Часть 1#
Работа со строками#
Строки в Python хранятся в Unicode.
В Python нет отдельного типа для одного символа. Символ это str
длинной 1.
Индексация#
str
индексируются как перечисляемые типы. К ним можно применять срезы и перечислять по символам.
s = "привет"
s[1] == "p" # True
for ss in s:
print(ss)
п
р
и
в
е
т
Изменение#
str
нельзя изменить.
Чтобы изменить строку надо создать новую из старой или превратить ее в список.
s = "привет"
s = s[0:1] + "Ф" + s[2:] # Успешно
s = "привет"
vs = list(s)
vs[1] = "Ф"
s = ''.join(vs) # Успешно
Некоторые методы#
find#
Поиск подстроки.
s = "hello world"
x = s.find("world") # x == 6
x = s.find("code") # x == -1
startswith и endswith#
Проверка, что строка начинается или заканчивается на подстроку.
s = "hello world"
x = s.startswith("hello") # x == True
x = s.endswith("code") # x == False
Конкатенация строк#
a = "hello"
b = "world"
c = a + " " + b #c == "hello world"
split#
Разбивает строку на список строк с использованием разделителя (по умолчанию пробел)
s = "goodbye|blue|sky"
d = s.split("|") # d == ['goodbye', 'blue', 'sky']
join#
Собирает строку из списка строк с использованием разделителя.
jp = ["goodbye", "blue", "sky"]
sep = "_"
s = sep.join(jp) # s == "goodbye_blue_sky"
strip#
Удаляет из начала и конца строки пробельные символы
s = "\t goodbye blue sky \n \n"
d = s.strip() # d == "goodbye blue sky"
replace#
Выполняет замену в строке.
s = "goodbye blue sky"
d = s.replace("blue", "red") # d == "goodbye red sky"
encode и decode#
Превращают str
в bytes
и обратно в заданной кодировке (по умолчанию utf8
).
s = "привет мир"
d = s.encode("cp866")
# d == b'\xaf\xe0\xa8\xa2\xa5\xe2 \xac\xa8\xe0'
q = d.decode("cp866")
# q == "привет мир"
ljust и rjust#
Догоняет строку заданным символом до нужной длинны.
s = "привет мир"
w = s.ljust(15,"_")
# w == 'привет мир_____'
q = s.rjust(15,"_")
# q == '_____привет мир'
Подстановка в строки#
Методы подстановки в Python:
В стиле printf:
"Привет %s!" % ("мир",)
В стиле format:
"Привет {}!".format("мир")
В стиле f-строк:
m = "мир"; f"Привет {m}!"
Формирование строк в стиле printf#
У типа str
предусмотрен оператор %
который принимает вторым аргументом кортеж и подставляет его элементы на указанные в шаблоне места.
t = "%s = %.2f"
s = t % ("A", 42)
# s == 'A = 42.00'
Популярные форматы#
Формат |
Ожидаемый тип |
Эффект |
Варианты с модификаторами |
---|---|---|---|
|
|
Подстановка строки |
|
|
|
Подстановка целого числа |
|
|
|
Подстановка числа в шестнадцатеричной системе |
|
|
|
Подстановка числа с плавающей точкой |
|
|
|
Экспоненциальный формат |
|
Примеры с использованием модификаторов#
print("%6d" % 42)
print("%06d" % 42)
print("%.2f" % 3.14159)
print("%06.2f" % 3.14159)
print("%#6.2f" % 3.14159)
print("%+6.3f" % 3.14159)
print("%+1.4e" % 3.14159)
42
000042
3.14
003.14
3.14
+3.142
+3.1416e+00
Формирование строк в стиле format#
У типа str
есть специальный метод format
:
s = 'Привет, {}!'
w = s.format('мир')
print(w)
Привет, мир!
Преимущества:
Автоматическое приведение типов
Возможность передачи параметров по имени и по номеру (в том числе повторение)
Форматы аналогичны %
но указываются после символа :
перед которым может стоять имя аргумента.
s = 'Power {power:.2f} State {state}'
w = s.format(state = "Ready", power = 3.14159)
print(w)
Power 3.14 State Ready
Формирование строк в стиле f-строк#
Строки могут быть созданы со специальным модификатором f который позволяет напрямую вставлять переменные в строку:
q = 'мир'
w = f'Привет, {q}!'
print(w)
Привет, мир!
Преимущества:
Автоматическое приведение типов
Отсутствие дублирования имен переменных в шаблоне и в программе
Форматы аналогичны %
но указываются после символа :
, как и в подстановках через format
.
power = 3.14159
state = "Ready"
w = f'Power {power:.2f} State {state}'
print(w)
Power 3.14 State Ready
Модификатор f
можно сочетать с модификатором r
, чтобы не обрабатывать спецсимволы.
filename = 'test'
fullpath = fr'c:\test\{filename}.txt'
Разбор строк#
Базовые разбор строк часто можно выполнить комбинацией методов split
, strip
и приведением полученных элементов строки к нужным типам. Но иногда этого бывает мало или получаемый код выходит слишком громоздким.
scanf#
Пакет scanf
предоставляет метод разбора строк аналогичный C функции scanf
.
from scanf import scanf
template = 'Power: %f [%], %s, Stemp: %f'
text = 'Power: 0.0 [%], Cool, Stemp: 23.73'
s = scanf(template, text)
print(s)
(0.0, 'Cool', 23.73)
Шаблон |
Значение |
---|---|
|
Один символ |
|
Пять символов |
|
Целое число |
|
Целое число в 7 символов |
|
Число с плавающей запятой |
|
Целое число в шестнадцатеричной системе |
|
Строка до первого пробела |
Поддерживаемые модификаторы: ширина поля %12d
и пропуск поля %*d
.
Дополнительно имеется тип %c
— один или нескольких символов, например %12c
, а %s
работает до первого пробела.
Подробное описание форматов scanf.
Регулярные выражения#
Регулярные выражения — специальный язык программирования. В стандартной библиотеке Python есть модуль для работы с ними — re
. Перед использованием регулярные выражения следует компилировать методом re.compile
, это повышает производительность.
Основные применения:
Проверка формальной корректности строки
Поиск/замена по шаблону
Разделение строки по правилам
Проверить свои регулярные выражения можно, например, на сайте http://www.pyregex.com/.
Использование длинных и сложных регулярных выражений считается плохим стилем. Для разбора сложного синтаксиса следует использовать другие инструменты.
Некоторые компоненты регулярных выражений:
Выражение |
Значение |
---|---|
|
Начало строки |
|
Конец строки |
|
Один любой символ |
|
Один из символов abcd |
|
Один из алфовитноцифровых символов |
|
Один символ из набора [a-zA-Z0-9_] + Unicode letters |
|
Один пробельный символ |
|
Группа из одного или нескольких шаблонов к которой можно обращаться |
|
Модификатор «один или несколько» |
|
Модификатор «ноль или несколько» |
Чтобы избежать проблем с экранированием регулярные выражения записываются, как строки без экранирования, например r'\w+'
.
Метод match#
Метод предназначен для проверки соответствие строки регулярному выражению.
import re
r = re.compile(r"\w+ = \w+")
print(r.match("Привет = мир"))
print(r.match("Привет ="))
print(r.match("Привет = мир проверка"))
<re.Match object; span=(0, 12), match='Привет = мир'>
None
<re.Match object; span=(0, 12), match='Привет = мир'>
r = re.compile(r"^\w+\s+=\s+\w+$")
print(r.match("Привет = мир проверка"))
print(r.match("Привет = мир\n"))
None
<re.Match object; span=(0, 12), match='Привет = мир'>
r = re.compile(r"^(\w+)\s+=\s+(\w+)$")
wd = r.match("Привет = мир")
print(wd.group(0))
print(wd.group(1))
print(wd.group(2))
Привет = мир
Привет
мир
Методы search и findall#
Поиск в строке подстрок(-и) удовлетворяющей выражению.
import re
r = re.compile(r"[а-я]+")
wd = r.search("Если я чешу в затылке не беда!")
s = wd.group(0) # s == 'сли'
t = r.findall("Если я чешу в затылке не беда!")
print(t)
['сли', 'я', 'чешу', 'в', 'затылке', 'не', 'беда']
Метод sub#
Замена подстрок(-и) удовлетворяющей выражению.
import re
r = re.compile(r"\s+")
s = r.sub("-","begin begin begin end end end")
print(s)
begin-begin-begin-end-end-end
Метод split#
Разбиение строки по разделителю в виде регулярного выражения.
import re
r = re.compile(r"\s+")
s = r.split("Если я чешу в затылке не беда!")
print(s)
['Если', 'я', 'чешу', 'в', 'затылке', 'не', 'беда!']
Дата и время#
В Python дата и время обычно используется в следующих формах:
Модуль
datetime
:datatime
— основной класс объектов времени. Объектdatatime
может быть по отношению к часовому поясу «naive» или «aware».timedelta
— класс интервала времени.
Модуль
time
— работа с временем в стиле Unixtime_t
(время выражается числом секунд с определенного момента, но имеет типfloat
— целая часть — число секунд, дробная — доли секунды).Модуль
calendar
— функции календаря.Модуль
zoneinfo
— данные по часовым поясам.
Дата и время (TZ naive)#
from datetime import datetime, timedelta
from time import time
t1 = time() # t1 == 1509532912.9569173
t2 = datetime.now()
# t2 == datetime.datetime(2017, 11, 1, 13, 42, 55, 774096)
t3 = datetime.fromtimestamp(t1)
# t3 == datetime.datetime(2017, 11, 1, 13, 44, 26, 259667)
t4 = datetime(year=2011,month=2,day=3,hour=12,minute=22,second=34)
# t4 == datetime.datetime(2011, 2, 3, 12, 22, 34)
t5 = t4.timestamp() # t5 == 1296724954.0
Дата и время (UTC)#
import datetime
import time
t7 = datetime.datetime.now()
print(t7)
print(t7.timestamp())
t8 = time.time() + time.timezone
print(t8)
t9 = datetime.datetime.fromtimestamp(t8)
print(t9)
2024-11-14 06:50:42.551622
1731556242.551622
1731545442.5517058
2024-11-14 03:50:42.551706
Дата и время (TZ aware)#
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
t_msk = datetime.now(ZoneInfo('Europe/Moscow'))
# t_msk == datetime.datetime(2017, 11, 1, 14, 52, 39, 297530, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
t_ber = datetime.now(ZoneInfo('Europe/Berlin'))
# t_ber == datetime.datetime(2017, 11, 1, 12, 52, 50, 681447, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
(t_msk - t_ber).total_seconds() < 0.001 # True
t_msk.astimezone(ZoneInfo('Europe/Berlin'))
# datetime.datetime(2017, 11, 1, 12, 55, 21, 842909, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
datetime.now().replace(tzinfo=ZoneInfo('Europe/Berlin'))
# datetime.datetime(2017, 11, 1, 15, 0, 59, 63396, tzinfo=<DstTzInfo 'Europe/Berlin' LMT+0:53:00 STD>)
datetime.datetime(2024, 11, 14, 6, 50, 42, 556834, tzinfo=zoneinfo.ZoneInfo(key='Europe/Berlin'))
Работа с интервалами#
Разность двух объектов datetime
дает объект timedelta
. Также его можно сконструировать через конструктор timedelta
. timedelta
можно складывать и вычитать, а также умножать на число.
from datetime import datetime, timedelta
from time import time
t1 = datetime(year=2013,month=7,day=15,hour=12,minute=22,second=34)
t2 = datetime.now()
td = t2 - t1
#td == datetime.timedelta(1570, 6567, 748425)
td.total_seconds() # 135654567.748425
t1 + timedelta(days=15)
# datetime.datetime(2013, 7, 30, 12, 22, 34)
timedelta(days=15) *2
# datetime.timedelta(30)
datetime.timedelta(days=30)
Для модификации datetime
к нему нужно или прибавить/отнять соответствующий timedelta
или обновить конкретные поля методом replace
.
Даты и время и строки#
Для приведения datetime
к строке и разбора строки в datetime
имеются функции strftime
и strptime
соответственно.
from datetime import datetime
t1 = datetime(year=2013,month=7,day=15,hour=12,minute=22,second=34)
t1.strftime("%d.%m.%Y %H:%M:%S")
print(t1)
t2 = datetime.strptime('15.07.2013 12:22:34', "%d.%m.%Y %H:%M:%S")
print(t2 == t1)
2013-07-15 12:22:34
True
Некоторые популярные форматы#
Формат |
Описание |
|
Пример |
---|---|---|---|
|
День месяца |
|
|
|
Месяц числом |
|
|
|
Год (2 знака) |
|
|
|
Год (4 знака) |
|
|
|
Час |
|
|
|
Минута |
|
|
|
Секунда |
|
|
|
День года |
|
|
Подробное описание форматов даты и времени.
Метод sleep#
Метод time.sleep
выполняет приостановку выполнения скрипта на заданное время в секундах и их долях.
import time
time.sleep(3)
time.sleep(0.23)
Работа с аргументами командной строки#
Аргументы командной строки — основной способ передачи параметров консольным приложениям
Интерпретатор Python рассматривает все аргументы переданные после имени скрипта, как аргументы скрипта
По традиции 0-вой аргумент — имя скрипта
Доступ к аргументам напрямую — список
argv
модуляsys
.
import sys
print(sys.argv)
['/usr/lib/python3.12/site-packages/ipykernel_launcher.py', '-f', '/tmp/tmpa3fhi2le.json', '--HistoryManager.hist_file=:memory:']
Пара слов о традициях обработки аргументов#
По традиции аргументы делятся на ключи/флаги и собственно аргументы. По традиции ключи/флаги начинаются с символа
-
По традиции ключи имеют собственные аргументы (
-x 258
), а флаги — нет (-x
).По традиции любой ключ/флаги программы может быть передан в короткой и длинной форме:
-o file.txt
--output-file file.txt
-v
--verbose
По традиции собственно аргументы передаются после ключей/флагов по порядку
python3 script.py -v -o file.txt Arg1 Arg2
Работа с модулем argparse#
Для разбора аргументов командной строки в стандартной библиотеке есть модуль argparse:
Создать объект — парсер
Описать возможные аргументы с помощью вызовов функций парсера
Запустить паресер
Парсер сконструирует объект в полях которого будут значения соответствующих аргументов
Описание аргументов#
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true",
default=False, help="Подробный вывод")
parser.add_argument("-i", "--input", action="store", required=True,
help="Входной файл (обязательный аргумент)")
parser.add_argument("-o", "--output", action="store", default="out.dat",
help="Выходной файл (по умолчанию out.dat)")
parser.add_argument('var', type=int,
help='Первый обязательный аргумент')
parser.add_argument('livar', nargs='+',
help='Один или более обязательных аргументов');
Автоматическая генерация справки#
> python3 test.py
usage: test.py [-h] [-v] -i INPUT [-o OUTPUT] var livar [livar ...]
test.py: error: the following arguments are required: -i/--input, var, livar
> python3 test.py -h
usage: test.py [-h] [-v] -i INPUT [-o OUTPUT] var livar [livar ...]
positional arguments:
var Первый обязательный аргумент
livar Один или более обязательных аргументов
optional arguments:
-h, --help show this help message and exit
-v, --verbose Подробный вывод
-i INPUT, --input INPUT
Входной файл (обязательный аргумент)
-o OUTPUT, --output OUTPUT
Выходной файл (по умолчанию out.dat)