Skip to content

3. Основи Python

Image

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)

Синтаксис форматованого рядка такий:

f'…{expr1:format1} …. {expr2:format2} ….'

де:

  • [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 символів;

Результати виконання такі:

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_02.py
[int1=10]
[int1=  10]
[int1=0010]
[float1=8.2]
[float1=    8.20]
[float1=8.200e+00]
[str1=abcd]
[str1=abcd    ]
[jean de fl          ]
[jean de fl          ]

Process finished with exit code 0

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 — це спеціальне значення, яке означає, що змінна існує, але не має значення.

Результати на екрані такі:

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_03.py
4 <class 'int'>
4 <class 'str'>
4.0 <class 'float'>
True <class 'bool'>
True <class 'bool'>
1 <class 'int'>
1.0 <class 'float'>
True <class 'str'>
4 <class 'str'>
4 <class 'int'>
4.0 <class 'float'>
True <class 'bool'>
4.32 <class 'float'>
4.32 <class 'str'>
4 <class 'int'>
True <class 'bool'>
invalid literal for int() with base 10: 'abc'
True <class 'bool'>
False <class 'bool'>
False <class 'bool'>
None <class 'NoneType'>
False <class 'bool'>
False <class 'bool'>
Abc
3
1
False

Process finished with exit code 0

Зауважимо, що всі дані є об’єктами, тобто екземплярами класу. Це означає, що вони можуть мати методи. Саме це показано в рядках 63–75 коду. Ми не намагаємося тут пояснити, що роблять використані методи, а просто показати, що вони існують.

3.4. Скрипт [bases_04]: область дії змінних

Скрипт [bases_04] показує, що в Python немає поняття змінної з блоковою областю дії:


# область дії змінних
i = 4
if True:
    i += 1
    j = 7
print(f"i={i}, j={j}")

Результати

1
2
3
4
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_04.py
i=5, j=7

Process finished with exit code 0

Коментарі

Результати показують дві речі:

  • рядок 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