3. Основи Python

3.1. Скрипт [bases_01]: елементарні операції
Скрипт [bases_01] демонструє перші особливості Python.
# ----------------------------------
def affiche(chaine):
# виводить рядок
print("chaine=%s" % chaine)
# ----------------------------------
def affiche_type(variable):
# відображає тип змінної
print("type[%s]=%s" % (variable, type(variable)))
# ----------------------------------
def f1(param):
# додає 10 до параметра
return param + 10
# ----------------------------------
def f2():
# повертає кортеж із 3 значень
return "un", 0, 100
# -------------------------------- головна програма ------------------------------------
# це коментар
# змінна, що використовується без оголошення
nom = "dupont"
# виведення на екран
print("nom=%s" % nom)
# список з елементами різних типів
liste = ["un", "deux", 3, 4]
# кількість елементів
n = len(liste)
# цикл
for i in range(n):
print("liste[%d]=%s" % (i, liste[i]))
# ініціалізація двох змінних за допомогою кортежу
(chaine1, chaine2) = ("chaine1", "chaine2")
# об'єднання двох рядків
chaine3 = chaine1 + chaine2
# виведення результату
print("[%s,%s,%s]" % (chaine1, chaine2, chaine3))
# використання функції
affiche(chaine1)
# тип змінної може бути відомим
affiche_type(n)
affiche_type(chaine1)
affiche_type(liste)
# тип змінної може змінюватися під час виконання
n = "a changé"
affiche_type(n)
# функція може повертати результат
res1 = f1(4)
print("res1=%s" % res1)
# функція може повертати список значень
(res1, res2, res3) = f2()
print("(res1,res2,res3)=[%s,%s,%s]" % (res1, res2, res3))
# ці значення можна було б зберегти у змінній
liste = f2()
for i in range(len(liste)):
print("liste[%s]=%s" % (i, liste[i]))
# тести
for i in range(len(liste)):
# відображає лише рядки
if type(liste[i]) == "str":
print("liste[%s]=%s" % (i, liste[i]))
# інші тести
for i in range(len(liste)):
# виводить лише цілі числа >10
if type(liste[i]) == "int" and liste[i] > 10:
print("liste[%s]=%s" % (i, liste[i]))
# цикл while
liste = (8, 5, 0, -2, 3, 4)
i = 0
somme = 0
while i < len(liste) and liste[i] > 0:
print("liste[%s]=%s" % (i, liste[i]))
somme += liste[i] # сума = сума + список[i]
i += 1 # i = i + 1
print("somme=%s" % somme)
# кінець програми
Коментарі
- рядок 2: ключове слово def визначає функцію;
- рядок 2: функція отримує параметр [chaine]. Тип параметра не вказується. Python використовує виключно передачу за значенням. Це значення залежить від типу даних:
- для простих типів (число, логічне значення тощо) це значення є значенням, яке інкапсулює даний елемент (4, True тощо);
- для складного типу (список, клас тощо) це значення є адресою даних;
- рядки 3–4: вміст функції. Він відступлений вправо на один табулятор. Саме цей відступ у поєднанні зі символом : в операторі def визначає вміст функції. Це стосується всіх операторів, що містять вміст: if, else, while, for, try, except;
- рядок 4: синтаксис, що використовується тут, — [print('text1%F1text2%F2…' % data1, data2)]:
- [%Fi] (тут %s) — це формати відображення:
- %s (string): для символьного рядка;
- %d (decimal): для цілих чисел із знаком;
- %f (float): десятковий формат для дійсних чисел;
- %e (exponentiel): експоненціальний формат для дійсного числа;
- …
- [data1, data2…] — це вирази, значення яких потрібно відобразити:
- [data1] буде відображено у форматі F1;
- [data2] відображатиметься у форматі F2;
- …
- рядок 10: Python внутрішньо керує типами змінних. Тип змінної можна дізнатися за допомогою функції type(variable), яка повертає змінну типу «type». Вираз «%s» % (type(variable)) — це рядок, що позначає тип змінної;
- рядок 25: головна програма. Зазвичай (але не обов’язково) вона йде після визначення всіх функцій скрипта. Її вміст не має відступів;
- рядок 28: у Python змінні не оголошуються. Python чутливий до регістру. Змінна Nom відрізняється від змінної nom. Строку можна взяти в лапки " або апострофи '. Отже, можна написати 'dupont' або "dupont";
- рядок 34: існує різниця між кортежем (1,2,3) (зверніть увагу на дужки) та списком [1,2,3] (зверніть увагу на квадратні дужки). Кортеж є незмінним, тоді як список — змінним. В обох випадках елемент № i позначається як [i];
- рядок 40: range(n) — це кортеж (0,1,2,…,n-1);
- рядок 41: формат %d використовується для цілих чисел зі знаком;
- рядок 74: len(var) — це кількість елементів колекції var (кортеж, список, словник…);
- рядок 84: структура [for in …] дозволяє виконувати ітерацію над ітерабельною структурою. Списки та кортежі є ітерабельними елементами;
- рядок 86: інші булеві оператори — це or та not;
- рядок 93: обчислює суму чисел >0 зі списку;
Результати на екрані такі:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_01.py
nom=dupont
liste[0]=un
liste[1]=deux
liste[2]=3
liste[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[4]=<class 'int'>
type[chaine1]=<class 'str'>
type[['un', 'deux', 3, 4]]=<class 'list'>
type[a changé]=<class 'str'>
res1=14
(res1,res2,res3)=[un,0,100]
liste[0]=un
liste[1]=0
liste[2]=100
liste[0]=8
liste[1]=5
somme=13
Process finished with exit code 0
3.2. Скрипт [bases_02]: форматування рядків
Python 3 запровадив новий спосіб форматування рядків:
# форматувальні рядки
# формати відповідають мові C
# ціле число
int1 = 10
print(f"[int1={int1}]")
print(f"[int1={int1:4d}]")
print(f"[int1={int1:04d}]")
# число з плаваючою комою
float1=8.2
print(f"[float1={float1}]")
print(f"[float1={float1:8.2f}]")
print(f"[float1={float1:.3e}]")
# рядок
str1="abcd"
print(f"[str1={str1}]")
print(f"[str1={str1:8s}]")
str2="jean de florette"
print(f"[{str2:20.10s}]")
# форматовані рядки можна присвоювати змінним
str3=f"[{str2:20.10s}]"
print(str3)
Синтаксис форматованого рядка такий:
де:
- [expri] — вираз;
- [formati]: формат виразу [expri]. Ці формати відповідають форматам мови C:
- %d: для цілих чисел;
- %f: десяткова нотація для дійсних чисел;
- %e: експоненціальне представлення для дійсних чисел;
- %s: для символьних рядків. Цей формат використовується, коли для [expri] не вказано жодного формату;
- %nd, %nf, %ns: виводить [expri], заповнюючи n символів: рядок або обрізається, або доповнюється пробілами;
- рядок 7: [04d], ціле число довжиною 4 символи, доповнене зліва нулями;
- рядок 11: [8.2f], десяткове число, що складається з 8 символів, з яких 2 — після коми;
- рядок 12: [.3e], дійсне число в експоненційному форматі з 3 знаками після коми для мантиси;
- рядок 18: [20.10s], перші 10 символів рядка, доповнені пробілами до 20 символів;
Результати виконання такі:
3.3. Скрипт [bases_03]: зміни типів
Тут ми розглянемо зміни типів даних типу str (рядок символів), int (ціле число), float (дійсне число), bool (логічне значення).
# зміна типів
# int --> str, float, bool
x = 4
print(x, type(x))
x = str(4)
print(x, type(x))
x = float(4)
print(x, type(x))
x = bool(4)
print(x, type(x))
# bool --> int, float, str
x = True
print(x, type(x))
x = int(True)
print(x, type(x))
x = float(True)
print(x, type(x))
x = str(True)
print(x, type(x))
# str → int, float, bool
x = "4"
print(x, type(x))
x = int("4")
print(x, type(x))
x = float("4")
print(x, type(x))
x = bool("4")
print(x, type(x))
# float → str, int, bool
x = 4.32
print(x, type(x))
x = str(4.32)
print(x, type(x))
x = int(4.32)
print(x, type(x))
x = bool(4.32)
print(x, type(x))
# обробка помилок при зміні типу
try:
x = int("abc")
print(x, type(x))
except ValueError as erreur:
print(erreur)
# різні випадки
x = bool("abc")
print(x, type(x))
x = bool("")
print(x, type(x))
x = bool(0)
print(x, type(x))
x = None
print(x, type(x))
x = bool(None)
print(x, type(x))
x = bool(0.0)
print(x, type(x))
# усі дані є екземплярами класів і, як такі, мають методи
# рядок символів
str1 = "abc"
print(str1.capitalize())
# ціле число
int1 = 4
print(int1.bit_length())
# логічне значення
bool1=True
print(bool1.conjugate())
# дійсне число
float1=8.2
print (float1.is_integer())
Можливі численні зміни типів. Деякі з них можуть завершитися невдачею, як-от у рядках 46–47, де робиться спроба перетворити рядок «abc» на ціле число. Помилку було оброблено за допомогою структури try / except. Загальний вигляд цієї структури
така:
try:
actions
except Exception as ex:
actions
finally:
actions
Якщо одна з дій блоку try викликає виняток (сигналізує про помилку), відбувається негайне перехоплення до блоку except. Якщо дії блоку try не викликають винятку, блок except ігнорується. Атрибути Exception та ex оператора except є необов’язковими. Якщо вони присутні, Exception визначає тип винятку, перехопленого інструкцією except, а ex містить виняток, що стався. Може бути кілька команд except, якщо потрібно обробляти різні типи винятків у одній команді try.
Інструкція finally є необов’язковою. Якщо вона присутня, дії з finally виконуються завжди, незалежно від того, чи сталося виключення.
Ми повернемося до винятків трохи пізніше.
У рядках 49–61 показано різні спроби перетворення даних типів str, int, float, NoneType у булеві значення. Це завжди можливо. Правила такі:
- bool(int i) дорівнює False, якщо i дорівнює 0, і True у всіх інших випадках;
- bool(float f) дорівнює False, якщо f дорівнює 0.0, і True у всіх інших випадках;
- bool(str chaine) дорівнює False, якщо chaine має 0 символів, True у всіх інших випадках;
- bool(None) дорівнює False. None — це спеціальне значення, яке означає, що змінна існує, але не має значення.
Результати на екрані такі:
Зауважимо, що всі дані є об’єктами, тобто екземплярами класу. Це означає, що вони можуть мати методи. Саме це показано в рядках 63–75 коду. Ми не намагаємося тут пояснити, що роблять використані методи, а просто показати, що вони існують.
3.4. Скрипт [bases_04]: область дії змінних
Скрипт [bases_04] показує, що в Python немає поняття змінної з блоковою областю дії:
# область дії змінних
i = 4
if True:
i += 1
j = 7
print(f"i={i}, j={j}")
Результати
Коментарі
Результати показують дві речі:
- рядок 4: змінна [i] з блоку [if] є тією самою, що й змінна i, використана в рядку 2;
- рядок 6: змінна [j] — це та, що ініціалізована у блоці [if];
У деяких мовах програмування, де змінні оголошуються, змінна, визначена в блоці (як у рядках 3–5), не є відомою поза межами цього блоку. У Python такого немає.
3.5. Скрипт [bases_05]: списки — 1
Скрипт [bases_05] має такий вигляд:
# одновимірні списки
# ініціалізація
list1 = [0, 1, 2, 3, 4, 5]
# обхід — 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
print(f"list1[{i}]={list1[i]}")
list1[1] = 10
# обхід — 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
print(element)
# додавання двох елементів
list1[len(list1):] = [10, 11]
# формат %s дозволяє відобразити список в одному рядку
print("%s" % list1)
# видалення двох останніх елементів
list1[len(list1) - 2:] = []
# формат за замовчуванням дозволяє відображати список в одному рядку
print(f"{list1}")
# додавання списку на початок списку
list1[:0] = [-10, -11, -12]
print(f"{list1}")
# вставлення двох елементів у середину списку
list1[3:3] = [100, 101]
print(f"{list1}")
# видалення двох елементів у середині списку
list1[3:4] = []
print(f"{list1}")
Примітки:
- позначення масив[i:j] позначає елементи від i до j-1 масиву;
- позначення [i:] означає елементи i та наступні елементи масиву;
- запис [:i] позначає елементи масиву від 0 до i-1;
- рядок 19: print (%s) % (list1) виводить рядок: «[ list1[0], list1[2]…, list1[n-1]]»;
- рядок 24: запис print ('f{list1}') виконує те саме;
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_05.py
list1 a 6 éléments
list1[0]=0
list1[1]=1
list1[2]=2
list1[3]=3
list1[4]=4
list1[5]=5
list1 a 6 éléments
0
10
2
3
4
5
[0, 10, 2, 3, 4, 5, 10, 11]
[0, 10, 2, 3, 4, 5]
[-10, -11, -12, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 100, 101, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 101, 0, 10, 2, 3, 4, 5]
Process finished with exit code 0
3.6. Скрипт [bases_06]: списки — 2
Попередній код можна написати інакше (bases_06), використовуючи певні методи списків:
# одновимірні списки
# ініціалізація
list1 = [0, 1, 2, 3, 4, 5]
# обхід — 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
print(f"list1[{i}]={list1[i]}")
# зміна елемента
list1[1] = 10
# обхід — 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
print(element)
# додавання двох елементів
list1.extend([10, 11])
print(f"{list1}")
# видалення двох останніх елементів
del list1[len(list1) - 2:]
print(f"{list1}")
# додавання кортежу на початок списку
for i in (-12, -11, -10):
list1.insert(0, i)
print(f"{list1}")
# вставка в середину списку
for i in (101, 100):
list1.insert(3, i)
print(f"{list1}")
# видалення з середини списку
del list1[3:4]
print(f"{list1}")
Отримані результати такі самі, як і в попередній версії.
3.7. скрипт [bases_07]: словник
Скрипт [bases_07] демонструє, як визначити та використовувати словник, який іноді називають асоціативним масивом.
# функція, яка перевіряє, чи існує ключ «mari» у словнику «conjoints»
def existe(conjoints, mari):
if mari in conjoints:
print(f"La clé [{mari}] existe associée à la valeur [{conjoints[mari]}]")
else:
print(f"La clé [{mari}] n'existe pas")
# ----------------------------- Головна
# словник
conjoints = {"Pierre": "Gisèle", "Paul": "Virginie", "Jacques": "Lucette", "Jean": ""}
# проходження — 1
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
for (clé, valeur) in conjoints.items():
print(f"conjoints[{clé}]={valeur}")
# список ключів словника
print("liste des clés-------------")
clés = conjoints.keys()
print(f"{clés}")
# список значень словника
print("liste des valeurs------------")
valeurs = conjoints.values()
print(f"{valeurs}")
# пошук ключа
existe(conjoints, "Jacques")
existe(conjoints, "Lucette")
existe(conjoints, "Jean")
# видалення пари «ключ-значення»
del (conjoints["Jean"])
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
print(f"{conjoints}")
# ключі та значення словника не є списками
print(f"type des clés : {type(clés)}")
print(f"type des valeurs : {type(valeurs)}")
# їх можна перетворити на списки
lclés = list(clés)
print(f"clés : {type(lclés)}, {lclés}")
lvaleurs = list(valeurs)
print(f"valeurs : {type(lvaleurs)}, {lvaleurs}")
Примітки:
- рядок 11: жорстке визначення словника;
- рядок 15: conjoints.items() об’єднує список пар (ключ, значення) словника;
- рядок 20: conjoints.keys() повертає ключі словника;
- рядок 25: conjoints.values() повертає значення словника «conjoints»;
- рядок 3: «mari» у «conjoints» повертає True, якщо ключ mari існує у словнику conjoints, інакше — False;
- рядок 36: словник можна відобразити в одному рядку.
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_07.py
Nombre d'éléments du dictionnaire : 4
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
liste des clés-------------
dict_keys(['Pierre', 'Paul', 'Jacques', 'Jean'])
liste des valeurs------------
dict_values(['Gisèle', 'Virginie', 'Lucette', ''])
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
{'Pierre': 'Gisèle', 'Paul': 'Virginie', 'Jacques': 'Lucette'}
type des clés : <class 'dict_keys'>
type des valeurs : <class 'dict_values'>
clés : <class 'list'>, ['Pierre', 'Paul', 'Jacques']
valeurs : <class 'list'>, ['Gisèle', 'Virginie', 'Lucette']
Process finished with exit code 0
Примітки:
- Зверніть увагу на рядки 16–17 результатів: ключі та значення словника утворюють не список, а тип «dict_keys»;
- рядки 18–19: проста зміна типу дозволяє перетворити їх на тип [list];
3.8. скрипт [bases_08]: кортежі
Кортеж має схожість зі списком, але є незмінним:
# кортежі
# ініціалізація
tuple1 = (0, 1, 2, 3, 4, 5)
# обхід — 1
print(f"tuple1 a {len(tuple1)} elements")
for i in range(len(tuple1)):
print(f"tuple1[{i}]={tuple1[i]}")
# обхід — 2
print(f"tuple1 a {len(tuple1)} elements")
for element in tuple1:
print(element)
# кортеж можна відобразити в одному рядку
print(f"tuple1={tuple1}")
# кортеж не можна змінити
tuple1[0] = 10
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py
tuple1 a 6 elements
tuple1[0]=0
tuple1[1]=1
tuple1[2]=2
tuple1[3]=3
tuple1[4]=4
tuple1[5]=5
tuple1 a 6 elements
0
1
2
3
4
5
tuple1=(0, 1, 2, 3, 4, 5)
Traceback (most recent call last):
File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py", line 19, in <module>
tuple1[0] = 10
TypeError: 'tuple' object does not support item assignment
Process finished with exit code 1
Примітки:
- рядки 17–20 результатів: показують, що кортеж не можна змінювати.
3.9. Скрипт [bases_09]: багатовимірні списки та словники
Скрипт [bases_09] демонструє, як визначити та використовувати багатовимірний список або словник:
# багатовимірні списки
# ініціалізація
multi = [[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]
# обхід
for i1 in range(len(multi)):
for i2 in range(len(multi[i1])):
print(f"multi[{i1}][{i2}]={multi[i1][i2]}")
# виведення в одному рядку
print(f"multi={multi}")
# багатовимірні словники
# ініціалізація
multi = {"zéro": [0, 1], "un": [10, 11, 12, 13], "deux": [20, 21, 22, 23, 24]}
# перегляд
for (clé, valeur) in multi.items():
for i2 in range(len(valeur)):
print(f"multi[{clé}][{i2}]={multi[clé][i2]}")
# однорядкове відображення
print(f"multi={multi}")
Коментарі
- рядок 7: multi[i1] — це список;
- рядок 18: value — це список;
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_09.py
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi=[[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]
multi[zéro][0]=0
multi[zéro][1]=1
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
multi={'zéro': [0, 1], 'un': [10, 11, 12, 13], 'deux': [20, 21, 22, 23, 24]}
Process finished with exit code 0
3.10. Скрипт [bases_10]: зв’язки між рядками та списками
Скрипт [bases_10] демонструє, як витягти у список елементи рядка, розділені одним і тим самим роздільником.
# перетворення рядка у список
chaine = '1:2:3:4'
liste = chaine.split(':')
print(type(liste))
# відображення списку
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
# перетворення списку в рядок
chaine2 = ":".join(liste)
print(f"chaine2={chaine2}")
# додамо порожнє поле
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")
# відображення списку
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
# додамо ще одне порожнє поле
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")
# відображення списку
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")
Примітки:
- рядок 3: метод chaine.split(роздільник) розбиває рядок chaine на елементи, розділені séparateur, і повертає їх у вигляді списку. Таким чином, вираз '1:2:3:4'.split(":") має значення списку ('1','2','3','4');
- рядок 11: 'separateur'.join(liste) має значення у вигляді рядка символів 'liste[0]+separateur+liste[1]+separateur+…'.
Результати
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_10.py
<class 'list'>
liste a 4 éléments
liste=['1', '2', '3', '4']
chaine2=1:2:3:4
chaine=1:2:3:4:
liste a 5 éléments
liste=['1', '2', '3', '4', '']
chaine=1:2:3:4::
liste a 6 éléments
liste=['1', '2', '3', '4', '', '']
Process finished with exit code 0
3.11. Скрипт [bases_11]: регулярні вирази
Скрипт [bases_11] демонструє, як використовувати регулярні вирази:
# імпортуємо модуль регулярних виразів
import re
# --------------------------------------------------------------------------
def compare(modèle, chaine):
# порівнює рядок [chaîne] із шаблоном [modèle]
# відображення результатів
print(f"\nRésultats({chaine},{modèle})")
match = re.match(modèle, chaine)
if match:
print(match.groups())
else:
print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]")
# регулярні вирази в Python
# витяг різних полів із рядка
# шаблон: послідовність цифр, оточена довільними символами
# потрібно витягти лише послідовність цифр
modèle = r"^.*?(\d+).*?$"
# порівнюємо рядок із шаблоном
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")
# шаблон: послідовність цифр, оточена довільними символами
# потрібна послідовність цифр, а також поля, що йдуть перед нею та після неї
modèle = r"^(.*?)(\d+)(.*?)$"
# порівнюємо рядок із шаблоном
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")
# шаблон — дата у форматі дд/мм/рр
modèle = r"^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$"
compare(modèle, "10/05/97")
compare(modèle, " 04/04/01 ")
compare(modèle, "5/1/01")
# шаблон — десяткове число
modèle = r"^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$"
compare(modèle, "187.8")
compare(modèle, "-0.6")
compare(modèle, "4")
compare(modèle, ".6")
compare(modèle, "4.")
compare(modèle, " + 4")
# кінець
Примітки:
- зверніть увагу на модуль [re], імпортований у рядку 2. Саме він містить функції для роботи з регулярними виразами;
- рядок 10: порівняння рядка з регулярним виразом (шаблоном) повертає логічне значення True, якщо рядок відповідає шаблону, і False — у протилежному випадку;
- рядок 12: match.groups() — це кортеж, елементи якого є частинами рядка, що відповідають елементам регулярного виразу, взятим у дужки. У шаблоні:
- ^.*?(\d+).*?, match.groups() буде кортежем з одного елемента, оскільки є одна дужка;
- ^(.*?)(\d+)(.*?)$, match.groups() буде кортежем із 3 елементів, оскільки є три дужки;
- рядок 21: літеральний регулярний вираз записується як r"xxx". Саме символ r перетворює рядок на регулярний вираз;
Регулярні вирази дозволяють перевіряти формат символьного рядка. Таким чином, можна перевірити, чи рядок, що позначає дату, має формат дд/мм/рр. Для цього використовується шаблон, і рядок порівнюється з цим шаблоном. Отже, у цьому прикладі j, m та a мають бути цифрами. Шаблон дійсного формату дати — це «\d\d/\d\d/\d\d», де символ \d позначає цифру. У шаблоні можна використовувати такі символи:
Символ | Опис |
\ | Позначає наступний символ як спеціальний або літеральний. Наприклад, «n» відповідає символу «n», тоді як «\n» відповідає символу нового рядка. Послідовність «\\» відповідає «\», а «\(" відповідає «(». |
^ | Відповідає початку рядка. |
$ | Відповідає кінцю рядка. |
* | Відповідає попередньому символу, нуль або більше разів. Таким чином, «zo*» відповідає «z» або «zoo». |
+ | Відповідає попередньому символу один або кілька разів. Таким чином, «zo+» відповідає «zoo», але не «z». |
? | Відповідає попередньому символу, нуль або один раз. Наприклад, «a?ve?» відповідає «ve» у слові «lever». |
. | Відповідає будь-якому окремому символу, крім символу нового рядка. |
(шаблон) | Знайде modèle і збереже збіг. Відповідний підрядок можна витягти з колекції match.groups(). Щоб знайти збіги з символами в дужках ( ), використовуйте «\(» або «\)». |
x|y | Відповідає або x, або y. Наприклад, «z|foot» відповідає «z» або «foot». «(z|f)oo» відповідає «zoo» або «foo». |
{n} | n — це невід’ємне ціле число. Відповідає точно n, помноженому на символ. Наприклад, «o{2}» не відповідає «o» у слові «Bob», а відповідає двом першим «o» у слові «fooooot». |
{n,} | n — це невід’ємне ціле число. Відповідає щонайменше n-кратному значенню символу. Наприклад, «o{2,}» не відповідає «o» у слові «Bob», а всім «o» у слові «fooooot». «o{1,}» еквівалентно «o+», а «o{0,}» — «o*». |
{n,m} | m та n — це невід’ємні цілі числа. Відповідає щонайменше n і щонайбільше m повторень символу. Наприклад, «o{1,3}» відповідає трьом першим «o» у слові «foooooot», а «o{0,1}» дорівнює «o?». |
[xyz] | Набір символів. Відповідає одному з вказаних символів. Наприклад, «[abc]» відповідає «a» у слові «plat». |
[^xyz] | Негативний набір символів. Відповідає будь-якому символу, що не вказано. Наприклад, «[^abc]» відповідає «p» у слові «plat». |
[a-z] | Діапазон символів. Відповідає будь-якому символу у вказаному діапазоні. Наприклад, «[a-z]» відповідає будь-якій маленькій літері від «a» до «z». |
[^m-z] | Негативний діапазон символів. Відповідає будь-якому символу, якого немає у вказаній послідовності. Наприклад, «[^m-z]» відповідає будь-якому символу, якого немає між «m» і «z». |
\b | Відповідає межі, що позначає слово, іншими словами, позиції між словом і пробілом. Наприклад, «er\b» відповідає «er» у слові «lever», але не «er» у слові «verbe». |
\B | Відповідає межі, що не позначає слово. «en*t\B» відповідає «ent» у слові «bien entendu». |
\d | Відповідає символу, що позначає цифру. Еквівалентно [0-9]. |
\D | Відповідає символу, що не є цифрою. Еквівалентно [^0-9]. |
\f | Відповідає символу переходу на новий рядок. |
\n | Відповідає символу нового рядка. |
\r | Відповідає символу повернення каретки. |
\s | Відповідає будь-якому пробілу, включаючи пробіл, табуляцію, перехід на нову сторінку тощо. Еквівалентно "[ \f\n\r\t\v]". |
\S | Відповідає будь-якому символу, що не є пробілом. Еквівалентно «[^ \f\n\r\t\v]». |
\t | Відповідає символу табуляції. |
\v | Відповідає символу вертикального табуляції. |
\w | Відповідає будь-якому символу, що позначає слово та містить підкреслення. Еквівалентно «[A-Za-z0-9_]». |
\W | Відповідає будь-якому символу, що не позначає слово. Еквівалентно «[^A-Za-z0-9_]». |
\num | Відповідає num, де num — це додатне ціле число. Посилається на збережені відповідності. Наприклад, «(.)\1» відповідає двом послідовним однаковим символам. |
\n | Відповідає n, де n — це вісімкове значення екранування. Вісімкові значення екранування повинні складатися з 1, 2 або 3 цифр. Наприклад, «\11» і «\011» обидва відповідають символу табуляції. "\0011" еквівалентно "\001" & "1". Восьмиричні ескейп-значення не повинні перевищувати 256. Якщо це сталося, у виразі враховуватимуться лише перші дві цифри. Дозволяє використовувати коди ASCII у регулярних виразах. |
\xn | Відповідає n, де n — це шістнадцяткове значення екранування. Шістнадцяткові екрануючі значення обов’язково мають складатися з двох цифр. Наприклад, «\x41» відповідає «A». «\x041» дорівнює «\x04» та «1». Дозволяє використовувати коди ASCII у регулярних виразах. |
Елемент у шаблоні може зустрічатися один або кілька разів. Розглянемо кілька прикладів із символом \d, який позначає 1 цифру:
шаблон | значення |
\d | цифра |
\d? | 0 або 1 цифра |
\d* | 0 або більше цифр |
\d+ | 1 або більше цифр |
\d{2} | 2 цифри |
\d{3,} | щонайменше 3 цифри |
\d{5,7} | від 5 до 7 цифр |
Тепер уявімо собі шаблон, здатний описати очікуваний формат рядка:
пошуковий рядок | модель |
дата у форматі дд/мм/рр | \d{2}/\d{2}/\d{2} |
час у форматі hh:mm:ss | \d{2}:\d{2}:\d{2} |
ціле число без знака | \d+ |
послідовність пробілів, яка може бути порожньою | \s* |
ціле число без знака, перед яким або після якого можуть бути пробіли | \s*\d+\s* |
ціле число, яке може мати знак і перед яким або після якого можуть бути пробіли | \s*[+|-]?\s*\d+\s* |
число з дійсної області без знака, перед яким або після якого можуть бути пробіли | \s*\d+(.\d*)?\s* |
дійсне число, яке може мати знак і мати пробіли перед або після нього | \s*[+-]?\s*\d+(.\d*)?\s* |
рядок, що містить слово «just» | \bjuste\b |
Можна вказати, де саме в рядку шукати шаблон:
шаблон | значення |
^шаблон | модель починає рядок |
шаблон$ | шаблон завершує рядок |
^шаблон$ | шаблон починає і закінчує рядок |
шаблон | шаблон шукається у всьому рядку, починаючи з його початку. |
шуканий рядок | шаблон |
рядок, що закінчується знаком оклику | !$ |
рядок, що закінчується крапкою | \.$ |
рядок, що починається з послідовності // | ^// |
рядок, що складається лише з одного слова, за яким можуть йти або перед яким можуть стояти пробіли | ^\s*\w+\s*$ |
рядок, що містить два слова, за якими або перед якими можуть бути пробіли | ^\s*\w+\s*\w+\s*$ |
рядок, що містить слово secret | \bsecret\b |
Підмножини шаблону можна «витягувати». Таким чином, можна не тільки перевірити, чи відповідає рядок певному шаблону, але й витягнути з цього рядка елементи, що відповідають підмножинам шаблону, які були взяті в дужки. Отже, якщо ми аналізуємо рядок, що містить дату дд/мм/рр, і хочемо додатково виокремити елементи дд, мм, рр з цієї дати, ми використаємо шаблон (\d\d)/(\d\d)/(\d\d).
Результати скрипта
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_11.py
Résultats(xyz1234abcd,^.*?(\d+).*?$)
('1234',)
Résultats(12 34,^.*?(\d+).*?$)
('12',)
Résultats(abcd,^.*?(\d+).*?$)
La chaîne [abcd] ne correspond pas au modèle [^.*?(\d+).*?$]
Résultats(xyz1234abcd,^(.*?)(\d+)(.*?)$)
('xyz', '1234', 'abcd')
Résultats(12 34,^(.*?)(\d+)(.*?)$)
('', '12', ' 34')
Résultats(abcd,^(.*?)(\d+)(.*?)$)
La chaîne [abcd] ne correspond pas au modèle [^(.*?)(\d+)(.*?)$]
Résultats(10/05/97,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('10', '05', '97')
Résultats( 04/04/01 ,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('04', '04', '01')
Résultats(5/1/01,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
La chaîne [5/1/01] ne correspond pas au modèle [^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$]
Résultats(187.8,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '187.8')
Résultats(-0.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('-', '0.6')
Résultats(4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4')
Résultats(.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '.6')
Résultats(4.,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4.')
Résultats( + 4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('+', '4')
Process finished with exit code 0