Уяви, що тебе попросили пояснити дорогу до аптеки. Ти кажеш: «за рогом праворуч, там побачиш». Людина побачить. Вона знає, що таке ріг, вміє впізнати вивіску, обійде калюжу і перепитає, якщо заблукає. Тепер уяви, що замість людини перед тобою щось, що вміє лише чотири дії: зробити крок, повернутися ліворуч, повернутися праворуч, подивитися, що просто перед носом. І воно не перепитує ніколи.
Це і є комп'ютер. Програмування — мистецтво пояснювати дорогу такому виконавцю. Не «зрозумій мене правильно», а «крок, крок, поворот, крок». І якщо на третьому кроці там стіна — виконавець піде в стіну, бо йому так сказали.
У цій темі ми пройдемо шлях від того, що взагалі вміє машина, до того, чому для розмови з нею придумали сотні мов і чому саме Python став тією, з якої починають майже всі. Коду тут майже не буде — він почнеться з наступної теми.
01 / ВиконавецьВиконавець без здорового глузду
Комп'ютер — це пристрій, який уміє виконувати дуже прості дії дуже швидко й дуже буквально. «Просто» тут означає буквально: додати два числа, порівняти два числа, покласти число в комірку пам'яті, взяти число з комірки, перестрибнути на іншу інструкцію. Усе. Ані «знайди мені гарну картинку», ані «зрозумій, що я мав на увазі» серед цих дій немає.
Дві властивості роблять із цього списку щось могутнє. Перша — швидкість: сучасний процесор виконує приблизно мільярд простих дій за секунду на кожному ядрі. Друга — буквальність: той самий набір інструкцій із тими самими даними дасть той самий результат сьогодні, завтра й на іншому континенті.
Буквальність — це і подарунок, і прокляття. Подарунок: програму можна перевірити й довіряти їй. Прокляття: якщо ти помилився, машина не помітить помилки — вона сумлінно виконає її мільярд разів.
Спробуй сам. Нижче — робот на сітці. Він уміє три речі: крок уперед, поворот ліворуч, поворот праворуч. Склади для нього програму так, щоб він дійшов до прапорця, і натисни «крок» — побачиш, як він виконує команди по черзі, згори вниз.
Інтерактив 1 · Робот виконує рівно те, що написано
Натискай команди — вони додаються в програму. Потім «крок» або «виконати все». Сірі клітинки — стіни.
02 / АлгоритмАлгоритм: рецепт для машини
Те, що ти щойно склав для робота, називається алгоритмом (algorithm) — скінченна послідовність однозначних кроків, яка з вхідних даних отримує результат. Слово звучить науково, але алгоритми тебе оточують. Рецепт борщу — алгоритм. Інструкція до пральної машини — алгоритм. Пояснення, як дійти до аптеки, — теж.
Різниця між побутовим і машинним алгоритмом одна: у побутовому дозволено покладатися на здоровий глузд читача. Порівняй.
# рецепт для людини
Посолити за смаком.
Варити, доки не буде готово.
Обидва рядки для машини безглузді. «За смаком» — скільки це в грамах? «Доки не буде готово» — за якою ознакою перевіряти? Щоб рецепт став програмою, кожну обмовку треба замінити на щось вимірне:
# той самий рецепт, але однозначно
Додати 8 грамів солі.
Повторювати: варити 1 хвилину, потім проколоти виделкою.
Зупинитись, коли виделка входить без опору.
Ось цей перехід — від «за смаком» до «8 грамів» — і є головна робота програміста. Не набирання тексту, а перетворення розпливчастого наміру на точну послідовність кроків. Мова, якою ти потім це запишеш, — питання десяте.
Зверни увагу на другий рядок: там з'явилося слово «повторювати», а в третьому — «зупинитись, коли». Це вже два з трьох будівельних блоків будь-якої програми взагалі. Їх усього три:
- Послідовність — роби це, потім те, потім те. Саме так виконував команди робот вище.
- Розгалуження — якщо умова виконується, роби одне, інакше інше. «Якщо попереду стіна — повернути, інакше крок».
- Повторення — роби те саме, доки виконується умова. «Йди вперед, доки не впрешся».
Це не спрощення для новачків, а доведений факт: будь-який алгоритм, який узагалі можна записати, можна записати цими трьома конструкціями. Усе інше в мовах програмування — зручності поверх цих трьох. Ми розберемо кожну: розгалуження — у темі про умови, повторення — у темі про цикли.
03 / РівніТри поверхи над залізом
Тепер найцікавіше. Процесор не розуміє слів «вперед» чи «повторювати». Він розуміє числа — послідовність байтів, де кожна група означає інструкцію. Це машинний код (machine code), і виглядає він як набір шістнадцяткових чисел.
Писати ним можна. Перші програмісти саме так і робили, і це було пекло: одна помилка в одному байті — і програма робить щось геть інше, без жодного натяку де саме зламалось. Тому над машинним кодом надбудували поверхи. Кожен поверх забирає в тебе частину контролю і взамін віддає час і нерви. Покрути повзунок і подивись, як одна й та сама дія — «додати два числа й покласти результат» — виглядає на кожному поверсі.
Інтерактив 2 · Той самий крок на чотирьох рівнях
Задача одна: узяти два числа, додати, зберегти результат. Повзунок — рівень абстракції.
Розберімо, що саме додає кожен поверх.
Байти, які процесор виконує напряму. Максимум контролю, нуль зручності. Прив'язаний до конкретної моделі процесора: байти для x86-64 не запустяться на процесорі твого телефона.
Ті самі інструкції, але записані словами: mov, add,
jmp. Програма-асемблер механічно перекладає слова в байти — майже
один до одного. Читати можна, писати все ще боляче, до процесора все ще прив'язано.
Ось де стрибок. Ти пишеш c = a + b — і не думаєш, у якому регістрі
лежить a. Компілятор сам вирішує. Той самий текст можна перезібрати
під інший процесор. Але пам'яттю ти все ще керуєш вручну: попросив — сам і поверни.
Зникає ще один шар турбот: типи не оголошуємо, пам'ять не звільняємо — за цим стежить збирач сміття (garbage collector), який сам прибирає те, на що вже ніхто не посилається. Той самий файл запуститься і на ноутбуці, і на сервері, і на Raspberry Pi без жодної перезбірки.
04 / МовиНавіщо мов так багато
Мова програмування — це домовленість про те, як записувати алгоритм, щоб його можна було механічно перекласти на машинні інструкції. У неї, як у людської мови, є синтаксис (які символи в якому порядку дозволені) і семантика (що кожна конструкція означає).
Мов існують сотні, і активно використовують кілька десятків. Не тому, що програмісти не змогли домовитись. Тому, що мова — це компроміс, а компроміси різні задачі вимагають різні. Кожна мова обирає своє місце між чотирма протилежностями:
| компроміс | один полюс | інший полюс |
|---|---|---|
| швидкість | швидко виконується (C, Rust) | швидко пишеться (Python, Ruby) |
| контроль | ти керуєш пам'яттю (C) | за пам'яттю стежить машина (Python, Java) |
| помилки | ловляться до запуску (Rust, Java) | ловляться під час роботи (Python) |
| багатослівність | усе явно (Java) | усе коротко (Python) |
Найкращої мови не існує — існує доречна для задачі. Щоб побачити компроміс на власні
очі, ось одна крихітна задача трьома мовами: узяти три числа, порахувати їхнє середнє
арифметичне, надрукувати. Усі три програми роблять точно одне й те саме й виводять
9.0.
Інтерактив 3 · Одна задача, три мови
Порахувати середнє трьох чисел і надрукувати. Результат усюди однаковий: 9.0
05 / ЗапускКомпіляція проти інтерпретації
Отже, ти написав текст. Як він перетворюється на дію? Є два підходи, і різниця між ними — це різниця між перекладом книжки і синхронним перекладачем.
Компіляція — це переклад книжки. Окрема програма-компілятор бере весь твій текст, перевіряє його, перетворює на машинний код і кладе результат в окремий файл. Далі цей файл запускають — і він працює сам, без компілятора. Так влаштовані C, C++, Rust, Go.
Інтерпретація — це синхронний перекладач. Програма-інтерпретатор читає твій текст і одразу виконує, конструкцію за конструкцією. Окремого файлу з машинним кодом не з'являється; щоб запустити програму, інтерпретатор потрібен щоразу.
| ознака | компіляція | інтерпретація |
|---|---|---|
| швидкість | висока: код уже машинний | нижча: переклад іде під час роботи |
| помилки синтаксису | усі до запуску | частина — аж коли дійде виконання |
| запуск | потрібна збірка під кожну систему | той самий файл усюди, де є інтерпретатор |
| цикл правки | змінив → зібрав → запустив | змінив → запустив |
06 / ВсерединіЩо Python робить із твоїм файлом
Розберімо шлях повністю — на найкоротшій програмі, яку можна написати. Файл
hello.py, у ньому один рядок: print(2 + 3). Ти набираєш у
терміналі python3 hello.py. Далі відбувається п'ять речей, і кожну можна
подивитись окремо.
Інтерактив 4 · Від тексту до результату
Один рядок print(2 + 3) проходить конвеєр. Веди повзунок або натисни «програти».
__pycache__ із готовим байт-кодом. Наступного разу, якщо файл не змінився,
етапи 2-4 пропускаються — тому повторний запуск стартує помітно швидше.
Видаляти цю теку безпечно, вона відновиться.Зверни увагу на етап 4. У байт-коді немає ані двійки, ані трійки — там одразу
5. Компілятор порахував 2 + 3 ще до запуску, бо обидва
доданки відомі заздалегідь. Це називають згортанням констант
(constant folding), і це єдина серйозна оптимізація, яку CPython робить сам.
python3 -m dis hello.py надрукує ті самі інструкції, що показані на
етапі 4. Ми зробимо це в практиці.07 / ВибірЧому саме Python
Python з'явився на початку 1990-х. Його автор, Гвідо ван Россум, ставив за мету
мову, яку легко читати — і саме читабельність виявилась вирішальною. Логіка проста:
код пишуть один раз, а читають десятки разів — і сам автор через півроку, і колеги,
і той, хто прийде після. Тому Python свідомо жертвує стислістю заради ясності:
ключові слова замість символів (and, а не &&),
відступи замість фігурних дужок.
Друга причина — бібліотеки. Бібліотека — це чужий код, який ти підключаєш до свого, щоб не писати заново. Для Python їх написано понад пів мільйона пакунків: робота з таблицями, графіки, вебсервери, нейромережі, розбір PDF. Практично будь-яка типова задача вже кимось розв'язана.
Третя — спільнота. Це не сентиментальність, а дуже практична річ: на будь-яке твоє питання новачка вже є десять відповідей, десяток книжок і документація українською. У маловідомої мови з ідеальним дизайном такого немає, і кожна дрібна проблема стає власним дослідженням на пів дня.
Але «Python хороший» — це реклама, а не знання. Знання — це розуміти, де він хороший. Веди повзунок по списку задач.
Інтерактив 5 · Де Python доречний, а де ні
Дев'ять типових задач. Повзунок обирає задачу, стовпчик показує, наскільки Python тут на місці.
08 / МежіДе Python поганий вибір
Тепер чесно про слабкі місця. Їх три, і всі три — прямий наслідок того, що ми розібрали вище.
Швидкість виконання
Пригадай поверхи з розділу 03. Коли C додає два числа, процесор виконує одну інструкцію. Коли Python додає два числа, віртуальна машина мусить: дістати обидва об'єкти, з'ясувати їхні типи, знайти для цих типів операцію додавання, викликати її, створити новий об'єкт під результат і врахувати його для збирача сміття. Десятки машинних інструкцій замість однієї.
Що це означає на практиці — залежить від обсягу. Порухай повзунок.
Інтерактив 6 · Скільки коштує повільність
Одна проста арифметична дія, повторена N разів. Логарифмічна шкала.
Мобільні застосунки
Тут проблема не в швидкості, а в екосистемі. Apple і Google будували свої платформи навколо Swift і Kotlin: інструменти, документація, магазини застосунків — усе розраховане на них. Kivy й BeeWare дозволяють зібрати застосунок на Python, але це постійна боротьба з течією.
Помилки, які видно лише в роботі
Java не дасть себе зібрати, якщо ти передав рядок туди, де очікується число. Python із радістю запуститься — і впаде на цьому рядку, можливо, через годину роботи, можливо, у клієнта. Це прямий наслідок гнучкості, за яку ми його й любимо. Часткова відповідь — підказки типів (type hints) і перевірка окремим інструментом; цьому присвячена тема 29 курсу.
09 / ГлибшеДля тих, хто вже пише код
Цей розділ можна пропустити на першому читанні. Він для тих, хто вже щось програмував і хоче знати, як воно влаштоване насправді.
Python — це специфікація, CPython — це програма
Коли кажуть «Python повільний», майже завжди мають на увазі CPython —
еталонну реалізацію, написану на C, ту саму, що стоїть у тебе після
python3. Але сама мова — це специфікація, і реалізацій у неї кілька:
| реалізація | що це | навіщо |
|---|---|---|
| CPython | еталон, написаний на C | стандарт де-факто; уся екосистема C-розширень працює саме тут |
| PyPy | інтерпретатор із JIT-компіляцією | довгі обчислювальні цикли можуть прискоритись у кілька разів |
| MicroPython | урізаний Python для мікроконтролерів | влазить у кілька сотень кілобайтів пам'яті |
| Pyodide | CPython, зібраний у WebAssembly | дозволяє запускати Python прямо в браузері |
GIL у двох реченнях
GIL (Global Interpreter Lock, глобальне блокування інтерпретатора) — це замок усередині CPython, який гарантує, що байт-код у кожен момент часу виконує рівно один потік. Наслідок: кілька потоків у CPython не прискорять обчислення, скільки б ядер не було в процесора — вони будуть чекати одне на одного.
Чому цей замок узагалі існує: він робить внутрішні структури інтерпретатора безпечними
без дорогих блокувань на кожній операції, і саме завдяки йому однопотоковий код швидкий,
а писати C-розширення просто. Обхідні шляхи давно відпрацьовані: для обчислень беруть
окремі процеси замість потоків (multiprocessing), а бібліотеки
на кшталт NumPy відпускають GIL на час своєї роботи всередині C-коду. Для очікування
мережі чи диска GIL узагалі не заважає — потік, що чекає відповіді, замок не тримає.
Чому саме відступи
Питання, яке дратує майже кожного, хто прийшов із мов із фігурними дужками. Логіка така: у мовах із дужками структуру задають дужки, а читає людина за відступами — тобто існують два джерела правди, і вони можуть розійтися. Python просто прибрав одне з них. Ціна — код чутливий до пробілів; вигода — те, що ти бачиш, і є те, що виконається.
10 / ПідсумокЩо далі
Коротко, що ми маємо після цієї теми:
- Комп'ютер виконує прості інструкції буквально й по черзі. Робот, що йде в стіну, — не збій, а точне виконання твоєї помилки.
- Алгоритм — однозначна послідовність кроків. Уся програма складається з трьох цеглин: послідовність, розгалуження, повторення.
- Мови вишикувані поверхами над залізом. Кожен поверх забирає контроль і віддає час.
- Python спершу компілюється в байт-код, і вже байт-код інтерпретує віртуальна машина.
- Його сила — читабельність, бібліотеки, спільнота. Слабкість — швидкість гарячих циклів і мобільні платформи. І перше майже завжди лікують тим, що важку роботу віддають бібліотеці на C.
Ти вже знаєш, що таке програма і як вона виконується. Відкритим
лишилось найпрактичніше питання: де взяти той самий python3, куди писати
текст програми і що саме натиснути, щоб вона запустилась.
Саме про це наступна тема — «Встановлення й перший запуск».
Там ми поставимо Python, розберемось, що таке термінал і файл із розширенням
.py, напишемо перший рядок коду й побачимо його результат на екрані.
А поки — відкрий практику: там ти запустиш свою першу
програму просто в браузері, зміниш її, свідомо зламаєш і навчишся читати повідомлення
про помилку. Уміння читати помилки економить більше часу, ніж будь-яке інше.
Далі в темі
Теорію прочитано. Тепер закріпи її на практиці.