1. (Л) Вступ. Предмет і завдання курсу. Алгоритм, блок-схеми, програма, компіляція, інтерпретація¶
Зміст лекції¶
- Предмет і завдання курсу
- Що таке алгоритм
- Властивості алгоритму
- Способи запису алгоритмів
- Блок-схеми алгоритмів
- Базові алгоритмічні структури
- Програма та мова програмування
- Компіляція та інтерпретація
- Як виконується програма на Python
- Перша програма
Предмет і завдання курсу¶
Курс присвячений основам програмування на прикладі мови Python.
Головна мета курсу — не «вивчити Python», а навчитися мислити алгоритмічно: розкладати задачу на послідовність простих кроків, які може виконати комп'ютер. Мова програмування — це лише інструмент запису цих кроків.
Завдання курсу:
- навчитися формулювати алгоритм розв'язання задачі та записувати його у вигляді блок-схеми;
- освоїти базовий синтаксис Python: змінні, типи даних, розгалуження, цикли, функції;
- навчитися працювати з колекціями даних (списки, кортежі, множини, словники);
- навчитися читати та писати файли, обробляти помилки;
- познайомитися з основами об'єктно-орієнтованого програмування;
- сформувати навичку самостійно шукати відповіді в документації.
Чому саме Python?
- простий і читабельний синтаксис — увага зосереджена на алгоритмі, а не на боротьбі з мовою;
- величезна стандартна бібліотека та екосистема пакетів;
- одна з найпоширеніших мов у веб-розробці, аналізі даних, автоматизації, машинному навчанні;
- кросплатформність — той самий код працює на Linux, macOS та інших системах.
Що таке алгоритм¶
Алгоритм — це скінченна впорядкована послідовність чітко визначених дій, виконання яких приводить до розв'язання поставленої задачі за скінченний час.
Алгоритми оточують нас щодня, навіть поза комп'ютерами:
- рецепт приготування страви;
- інструкція зі складання меблів;
- правила переходу дороги на світлофорі;
- алгоритм ділення стовпчиком, який ви вивчали в школі.
Приклад побутового алгоритму — «Приготувати чай»:
- Налити воду в чайник.
- Увімкнути чайник.
- Чекати, доки вода закипить.
- Покласти пакетик чаю в чашку.
- Налити окріп у чашку.
- Чекати 3 хвилини.
- Вийняти пакетик.
Зверніть увагу: кроки впорядковані, кожен зрозумілий виконавцю, їх скінченна кількість, і в результаті ми отримуємо чай.
Виконавець алгоритму¶
Алгоритм завжди пишеться для конкретного виконавця. Виконавець має свою систему команд — набір дій, які він розуміє.
Для людини команда «посолити за смаком» зрозуміла. Для комп'ютера — ні: він не має поняття «за смаком». Комп'ютер розуміє лише точні, однозначні команди: додати, порівняти, перемістити значення, перейти до іншої команди.
Головна складність програмування
Комп'ютер робить не те, що ви хотіли, а те, що ви написали. Уся неоднозначність, яку в побутовій мові людина «добудовує» сама, у програмі має бути описана явно.
Властивості алгоритму¶
| Властивість | Пояснення | Приклад порушення |
|---|---|---|
| Дискретність | Алгоритм складається з окремих завершених кроків | «Розв'яжи задачу» — це не крок, а вся задача |
| Визначеність (детермінованість) | Кожен крок трактується однозначно; при тих самих вхідних даних результат однаковий | «Додай трохи цукру» — скільки саме? |
| Скінченність (результативність) | Алгоритм завершується за скінченну кількість кроків і дає результат | «Ділити 1 на 3, доки не поділиться націло» — не завершиться ніколи |
| Масовість | Алгоритм застосовний до цілого класу однотипних задач, а не до одного набору даних | Алгоритм, що вміє додавати лише 2 і 2 |
| Зрозумілість | Усі команди належать до системи команд виконавця | «Проінтегруй функцію» для калькулятора, що вміє лише +, −, ×, ÷ |
Приклад: алгоритм Евкліда¶
Класичний алгоритм пошуку найбільшого спільного дільника (НСД) двох натуральних чисел:
- Якщо
bдорівнює 0 — відповідьa, завершити. - Обчислити остачу
rвід діленняaнаb. - Присвоїти
aзначенняb, аb— значенняr. - Повернутися до кроку 1.
Перевіримо властивості: кроки дискретні й однозначні, алгоритм завершується (остача щоразу зменшується), працює для будь-яких натуральних чисел — тобто має масовість.
Способи запису алгоритмів¶
Один і той самий алгоритм можна записати різними способами.
graph LR
A["Алгоритм"] --> B["Словесний опис"]
A --> C["Псевдокод"]
A --> D["Блок-схема"]
A --> E["Програма<br/>мовою програмування"]
style D fill:#ffd43b,stroke:#333,color:#000
style E fill:#51cf66,stroke:#333,color:#000
1. Словесний опис — звичайною мовою, як приклад із чаєм вище. Зрозумілий людині, але громіздкий і схильний до двозначності.
2. Псевдокод — напівформальний запис, схожий на програму, але без прив'язки до синтаксису конкретної мови:
3. Блок-схема — графічне зображення алгоритму. Наочно показує структуру та порядок виконання.
4. Програма — запис алгоритму мовою програмування, придатний для виконання комп'ютером.
Блок-схеми алгоритмів¶
Блок-схема — графічне подання алгоритму, де кожна дія зображується геометричною фігурою певної форми, а порядок виконання — стрілками. Форми блоків стандартизовані (ISO 5807, ДСТУ ISO 5807).
Основні блоки¶
| Блок | Форма | Призначення |
|---|---|---|
| Термінатор | Овал / заокруглений прямокутник | Початок або кінець алгоритму |
| Процес | Прямокутник | Обчислення, присвоєння значення |
| Введення/виведення | Паралелограм | Отримання вхідних даних, виведення результату |
| Рішення | Ромб | Перевірка умови, розгалуження |
| Підпрограма | Прямокутник з подвійними бічними лініями | Виклик іншого алгоритму (функції) |
| З'єднувач | Коло | Розрив і продовження лінії на схемі |
| Лінія потоку | Стрілка | Порядок виконання блоків |
graph TD
A(["Термінатор: початок / кінець"]) --> B[/"Введення / виведення даних"/]
B --> C["Процес: обчислення"]
C --> D{"Рішення: умова?"}
D -->|так| E["Дія 1"]
D -->|ні| F["Дія 2"]
style A fill:#51cf66,stroke:#333,color:#000
style B fill:#339af0,stroke:#333,color:#fff
style C fill:#e9ecef,stroke:#333,color:#000
style D fill:#ffd43b,stroke:#333,color:#000
Правила побудови блок-схем¶
- Схема має рівно один блок «початок» і щонайменше один блок «кінець».
- Кожен блок, окрім термінаторів, має один вхід; блок «рішення» має один вхід і два виходи (
так/ні). - Лінії потоку не перетинаються без потреби; стандартний напрямок — згори вниз і зліва направо.
- Гілки розгалуження обов'язково підписуються.
- Текст усередині блоку — короткий і однозначний.
Приклад 1: найбільше з двох чисел¶
graph TD
S(["Початок"]) --> IN[/"Ввести a, b"/]
IN --> Q{"a > b ?"}
Q -->|так| M1["max = a"]
Q -->|ні| M2["max = b"]
M1 --> OUT[/"Вивести max"/]
M2 --> OUT
OUT --> E(["Кінець"])
style S fill:#51cf66,stroke:#333,color:#000
style E fill:#ff6b6b,stroke:#333,color:#fff
style Q fill:#ffd43b,stroke:#333,color:#000
Той самий алгоритм мовою Python:
a = int(input("a = "))
b = int(input("b = "))
if a > b:
biggest = a
else:
biggest = b
print("max =", biggest)
Приклад 2: сума чисел від 1 до N¶
graph TD
S(["Початок"]) --> IN[/"Ввести n"/]
IN --> INIT["total = 0<br/>i = 1"]
INIT --> Q{"i <= n ?"}
Q -->|так| ADD["total = total + i"]
ADD --> INC["i = i + 1"]
INC --> Q
Q -->|ні| OUT[/"Вивести total"/]
OUT --> E(["Кінець"])
style S fill:#51cf66,stroke:#333,color:#000
style E fill:#ff6b6b,stroke:#333,color:#fff
style Q fill:#ffd43b,stroke:#333,color:#000
n = int(input("n = "))
total = 0
i = 1
while i <= n:
total = total + i
i = i + 1
print("total =", total)
Приклад 3: алгоритм Евкліда¶
graph TD
S(["Початок"]) --> IN[/"Ввести a, b"/]
IN --> Q{"b = 0 ?"}
Q -->|ні| R["r = остача a / b"]
R --> SW["a = b<br/>b = r"]
SW --> Q
Q -->|так| OUT[/"Вивести a"/]
OUT --> E(["Кінець"])
style S fill:#51cf66,stroke:#333,color:#000
style E fill:#ff6b6b,stroke:#333,color:#fff
style Q fill:#ffd43b,stroke:#333,color:#000
a = int(input("a = "))
b = int(input("b = "))
while b != 0:
r = a % b # остача від ділення
a = b
b = r
print("gcd =", a)
Базові алгоритмічні структури¶
Доведено (теорема Бома — Якопіні), що будь-який алгоритм можна побудувати з трьох базових структур.
graph LR
subgraph "Слідування"
A1["Дія 1"] --> A2["Дія 2"] --> A3["Дія 3"]
end
subgraph "Розгалуження"
B1{"умова?"} -->|так| B2["Дія A"]
B1 -->|ні| B3["Дія B"]
end
subgraph "Повторення"
C1{"умова?"} -->|так| C2["Тіло циклу"]
C2 --> C1
end
| Структура | Суть | Конструкція Python |
|---|---|---|
| Слідування | Дії виконуються послідовно, одна за одною | Рядки коду підряд |
| Розгалуження | Виконується одна з гілок залежно від умови | if / elif / else |
| Повторення (цикл) | Дія повторюється, доки виконується умова | while, for |
Саме тому в програмуванні немає потреби в операторі безумовного переходу (goto) — трьох структур достатньо, а код із ними залишається читабельним.
Програма та мова програмування¶
Програма — це алгоритм, записаний мовою програмування, тобто у формі, придатній для виконання комп'ютером.
Мова програмування — формальна мова з чітко визначеними правилами:
- синтаксис — правила запису конструкцій (де ставити двокрапку, дужки, відступи);
- семантика — значення цих конструкцій (що саме робить
while).
Порушення синтаксису робить програму невиконуваною — комп'ютер просто не зрозуміє запис. Порушення семантики («написав не те, що мав на увазі») дає програму, яка працює, але неправильно. Перше знаходить комп'ютер, друге — доводиться шукати вам.
Рівні мов програмування¶
graph TD
H["Мови високого рівня<br/>Python, Java, C#, JavaScript"] --> M["Мови середнього рівня<br/>C, C++, Rust"]
M --> L["Асемблер<br/>мнемоніки машинних команд"]
L --> B["Машинний код<br/>двійкові інструкції процесора"]
style H fill:#51cf66,stroke:#333,color:#000
style B fill:#495057,stroke:#333,color:#fff
Процесор виконує лише машинний код — послідовність двійкових інструкцій. Людині писати такий код украй незручно, тому програму пишуть мовою високого рівня, а спеціальна програма перетворює її на машинний код. Способів такого перетворення два: компіляція та інтерпретація.
Компіляція та інтерпретація¶
Компіляція¶
Компілятор — програма, яка повністю перекладає вихідний код у машинний код цільової платформи, створюючи виконуваний файл. Після цього програму можна запускати скільки завгодно разів без компілятора.
graph LR
SRC["Вихідний код<br/>program.c"] --> C["Компілятор"]
C --> EXE["Виконуваний файл<br/>program"]
EXE --> CPU["Процесор"]
style C fill:#339af0,stroke:#333,color:#fff
style EXE fill:#51cf66,stroke:#333,color:#000
Приклади компільованих мов: C, C++, Rust, Go.
Інтерпретація¶
Інтерпретатор — програма, яка читає вихідний код і виконує його покроково, конструкція за конструкцією, не створюючи окремого виконуваного файлу. Щоб запустити програму, інтерпретатор потрібен щоразу.
graph LR
SRC["Вихідний код<br/>program.py"] --> I["Інтерпретатор"]
I --> CPU["Процесор"]
style I fill:#ffd43b,stroke:#333,color:#000
Приклади інтерпретованих мов: Python, JavaScript, Ruby, PHP.
Порівняння¶
| Критерій | Компіляція | Інтерпретація |
|---|---|---|
| Коли перекладається код | Один раз, до запуску | Під час кожного запуску |
| Швидкість виконання | Висока | Нижча (накладні витрати інтерпретатора) |
| Виявлення помилок синтаксису | До запуску, у всьому файлі | Під час виконання, коли дійшло до рядка |
| Кросплатформність | Потрібна окрема збірка для кожної платформи | Той самий код працює всюди, де є інтерпретатор |
| Швидкість розробки | Нижча (цикл «змінив — зібрав — запустив») | Вища (змінив — запустив) |
| Потреба в інструменті у користувача | Ні, достатньо готового файлу | Так, потрібен інтерпретатор |
Це не властивість мови
Строго кажучи, компільованою чи інтерпретованою є не мова, а її реалізація. Існують інтерпретатори C і компілятори Python. Просто для кожної мови історично склалася найпоширеніша реалізація.
Як виконується програма на Python¶
Python поєднує обидва підходи. Стандартна реалізація (CPython) спочатку компілює вихідний код у проміжне подання — байткод, а потім інтерпретує цей байткод на віртуальній машині Python (PVM).
graph TD
SRC["Вихідний код<br/>program.py"] --> COMP["Компілятор Python"]
COMP --> BC["Байткод<br/>__pycache__/program.cpython-XX.pyc"]
BC --> PVM["Віртуальна машина Python (PVM)<br/>інтерпретатор байткоду"]
PVM --> CPU["Процесор"]
style COMP fill:#339af0,stroke:#333,color:#fff
style BC fill:#ffd43b,stroke:#333,color:#000
style PVM fill:#51cf66,stroke:#333,color:#000
Навіщо байткод? Це компроміс: розбір тексту програми (найповільніша частина) виконується один раз, а результат кешується в каталозі __pycache__. При наступному запуску, якщо файл не змінювався, Python одразу бере готовий байткод.
Байткод не залежить від операційної системи — залежить лише віртуальна машина. Саме тому один і той самий .py файл працює на різних платформах.
Подивитися байткод (додатково)
Стандартний модуль dis показує, у які інструкції перетворюється код:
У виведенні ви побачите інструкції віртуальної машини: завантажити значення a, завантажити b, виконати додавання, повернути результат. Це і є той рівень, на якому «мислить» PVM.
Реалізації Python¶
| Реалізація | Особливість |
|---|---|
| CPython | Еталонна реалізація мовою C, саме її ви завантажуєте з python.org |
| PyPy | Використовує JIT-компіляцію, часто працює значно швидше |
| Jython | Компілює в байткод Java, працює на JVM |
| MicroPython | Полегшена версія для мікроконтролерів |
У цьому курсі ми працюємо з CPython — коли говоримо «Python», маємо на увазі саме його.
Перша програма¶
Створіть файл hello.py з таким вмістом:
Запуск у терміналі:
Виведення:
Тут print — вбудована функція виведення тексту, а рядок у лапках — її аргумент. Компілятор Python перетворив цей рядок на байткод, а віртуальна машина його виконала.
Трохи змістовніший приклад — програма, що реалізує наш перший алгоритм (найбільше з двох чисел):
# Program: find the largest of two numbers
a = int(input("a = "))
b = int(input("b = "))
if a > b:
biggest = a
else:
biggest = b
print("The largest number is", biggest)
Приклад роботи:
Функція input() зчитує рядок з клавіатури, а int() перетворює цей рядок на ціле число. Детально ми розберемо їх на наступних заняттях.
Головна порада курсу
Не переходьте до написання коду, доки не сформулювали алгоритм. Спочатку — кроки на папері або блок-схема, потім — код. Це виглядає повільніше, але економить години налагодження.
Корисні посилання¶
- Офіційний сайт Python
- Документація Python
- The Python Tutorial
- Модуль dis — дизасемблер байткоду
- ISO 5807 — символи блок-схем
Домашнє завдання¶
- Встановити Python 3 та переконатися, що команда
python3 --versionвиводить версію. - Створити та запустити файл
hello.pyз програмою виведення тексту. - Скласти блок-схему алгоритму для однієї з задач:
- визначити, чи є введене число парним;
- обчислити добуток чисел від 1 до N (факторіал);
- визначити найменше з трьох введених чисел.
- Прочитати розділ An Informal Introduction to Python.
Знайшли помилку чи бажаєте додати інформацію, щоб покращити курс? Створіть issue на GitHub