Глава 16 Як розробляти фунцкії

⏱️ Час на опанування теми: 15 хвилин

🤷 Для чого ми це вивчаємо:

🔑 Результати навчання:

  • Розуміння що таке програма, додаток та програмне забезпечення
  • Розуміння що таке алгоритм, кодування та програмування

🎈 Увага: Наразі ця глава знаходиться у стані активної розробки і ймовірно буде змінюватись і доповнюватись!


У цій главі…


З попередніх глав, ми вже знаємо як написати функцію та навіщо їх взагалі використовувати. Але знати як написати фунцкію є зовсім іншою навичкою ніж знати як розробити фунцкію від початку і до конція. У цій главі ми спробуємо охопити усі етапи двох методів створення фунцкії та показати потік міркувань який призводить до кінечного результату. Ми розглянемо це все на на конкретному прикладі.

16.1 Будуємо фунцкію з нуля

16.1.1 Визначаємо мету функції

Усі розробки починаються з кінечної мети, тобто нам потрібно відповісти на наступні питання: для чого нам потрібна фунцкія і що вона повинна робити? Найкраще це формулуювати це реченням, щось накшталт: “Ця функція повинна…”

Наприклад, у нас є два списка температур повітря: поточного тиждня current_week та попереднього тиждня last_week. Нам треба з’ясувати чи був холодніший поточинй тиждень за попередній у середньому:

current_week = [19, 16, 15, 20, 20, 19, 15]
last_week = [14, 20, 16, 16, 17, 16, 15]

Для того щоб нам з’ясувати чи був холодніший один тиждень за інший у середньому, нам треба знайти середню температуру для кожного тидждня. Ось тут і з’вляється наша замотивованість написати фунцкію. Коли ми розуміємо що нам треба щось зробити більш ніж один раз – скоріш за все ми можемо загорнути це у фунцкію.

Окєй, ми замотивовані. Тепер треба відповісти на оті питання нагорі. Відповідь тут не складна: “Ця функція повинна знаходити середнє значення елементів списку.”. О, до речі, коли ми сформулювали що саме повинна робити функція, це може бути дуже кьовим кандидатом для назив фунцкії. Наприклад, назви get_average() або compute_mean() будуть як раз відображати що саме фунцкія робить. Але про це ми детальніше поговоримо у Додатку C.

16.1.2 Визначаємо параметри функції та що вона повинна повернути

Пам’ятаєте ми обговорювали абстракцію у попередній главі? Ми використаємо цей принцип тут – замість того, щоб зразу ж писати фунцкію, ми можемо абстрагуватись як вона це робить і сконцентруватись на вхідних та вихідних даних. Тобто на параметрах та значенні, яке повинна фунцкія повернути.

Так як фунцкія повинна розрахувати середне значення списку, то цей список і буде параметром. Нам не треба ніяких інших даних для обчислення. На виході ж буде скалярне значення типу float, яке ми назвемо mean:

Ми можемо вже побудувати “ескіз” нашої фунцкії:

def compute_mean(temperatures):
    # обчислити середнє mean
    return mean

16.1.3 Розроблюємо тіло функції

Коли вже у нас є розуміння “що” функція повинна робити, треба прописати “як” вона буде це робити. По суті, цей етап включає написання алгоритму та його реазізацію у вигляді коду. В нашому випадку, нам треба (1) знайти суму усіх елементів, (2) знайти довжину списку і нарешті (3) розділити суму елементів на кількість. Це й буде те значення яке нам треба повернути.

Тепер додаємо ці інструкції у код:

def compute_mean(temperatures):
    s = sum(temperatures)
    n = len(temperatures)
    mean = s / n
    return mean

Вуаля! Ось і готова наша функція! В принципі, ми можемо її вже використовувати. Але ми можемо її трохи покращіти. Наприклад, нам не треба створювати нові змінні s та n всередині функції – ми можемо використати вирази sum(temperatures) та len(temperatures) безпосередьно:

def compute_mean(temperatures):
    mean = sum(temperatures) / len(temperatures)
    return mean

Так само ми можемо замість mean прописати вираз якому він дорівнює:

def compute_mean(temperatures):
    return sum(temperatures) / len(temperatures)

Так, фунцкія готова, а як впевнитись що вона працює?

16.1.4 Тестуємо фунцкію

Для цього ми переходимо до наступної стадії – тестування. Тестування необхідне щоб зрозуміти, чи не зробили ми помилку. Все просто – ми будемо надавати вхідні дані, для яких ми знаємо що буде на виході. І потім порівнювати – чи збігається правильна відповідь з тим, що повернула функція.

Середнє значення списку [1, 2, 3] є 2. Давайте перевіряти:

compute_mean([1, 2, 3])
## 2.0

Давайте перевіримо ще раз, але цього разу з від’ємними часлами:

compute_mean([-10, -9, -8, -7, -6])
## -8.0

Здається працює! Тестування може здатись як зайвий крок, але він чи ненайголовніший. Тому що навіть якщо функція спроєктована правильно – яка з неї користь, якщо вона не працює? А дізнатись ми можемо тільки через тестування.

16.1.5 Використовуємо функцію

Нам залишилось тільки використати цю функцію для нашої задачі та відповісти на питання:

compute_mean(current_week)
## 17.714285714285715
compute_mean(last_week)
## 16.285714285714285

З цього витікає, що середня температура поточного тиждня не нижча за середню температуру попереднього тиждня.

16.2 Загортаємо код у фунцкію

Давайте тепер подивимось на інший підхід. Він пов’язаний з такою практикою, яка називається рефакторінг. Рефакторінг – це коли ми переписуємо або переструтуруємо наш код щоб поліпшити його чатабельність. Те що код робить при цьому не повинно бути змінненим.

Візьмемо ту ж саму задачу обчислання середнього значення. Вона вже вирішенна за допомогою наступного коду (без використання функції):

current_week = [19, 16, 15, 20, 20, 19, 15]

sum(current_week) / len(current_week)
## 17.714285714285715
last_week = [14, 20, 16, 16, 17, 16, 15]

sum(last_week) / len(last_week)
## 16.285714285714285

На що тут треба звернути увагу? На рядки sum(current_week) / len(current_week) та sum(last_week) / len(last_week). Вони практично однакові, і різняться тільки ім’ям змінної – current_week та last_week. Коли ми бачимо однакові рядки коду – це сингал що ми можемо їх “загорнути” у функцію.

Давайте загорнемо ці інструкції у функцію. Поки ми знаємо які саме параметри нам потрібні, тому замість параметрів ми залишемо ___. Так само ми використаємо заглушку ___ замість тих змінних, які відрізняються у коді:

def get_mean(___): 
    sum(___) / len(___)
    ...

Далі, треба звернути увагу чим саме вони відрізняються. Якщо це якась змінна – це підказка на те, що може бути параметрами функції. У нашому випадку це ім’я списку, замість якого ми поставили ___. Залишилось тільки повернути значення, щоб фунцкія збігалася з тим кодом, який ми заміняємо:

def get_mean(temperatures): 
    return sum(temperatures) / len(temperatures)

І тепер ми можемо використати цю функцію замість коду:

current_week = [19, 16, 15, 20, 20, 19, 15]

get_mean(current_week)
## 17.714285714285715
last_week = [14, 20, 16, 16, 17, 16, 15]

get_mean(last_week)
## 16.285714285714285


🤸 Вправи
1. Чи можна будувати функцію без кінцевої мети?
2. Котра з функцій правильно обчислить площу квадрата?
1. ddef calculate_square(a): 
    return a * a

2. def calculate_square(a) 
    return a * a

3. def calculate_square(a): 
    return a + a



Оберіть правильну відповідь:
3. Що таке значення за замовчуванням у параметрах функції?
4. Що таке тестування функції?
5. Що потрібно написати замість квадратних дужок, щоб функція правильно поряхувала площу прямокутника?
def calculate_rectangle_area(length, width):
   area = length * width
   return []

Напишіть правильну відповідь:
6. Якщо довжина та ширина прамокутника дорівнюють 3 та 5 відповідно. Яка буде площа цього прямокутника?