НМЦ

Програмування мовою Python: основи та практика

Електронний посібник

ВФПО

ТЕМА 8. ФУНКЦІЇ

 

8. Функції

8.1. Опис та виклик функції

8.2. Розширене використання параметрів та аргументів

8.3. Значення початкових параметрів

8.4. Ключові аргументи

8.5. Змінна кількість аргументів

8.6. Обов’язкові ключові аргументи

8.7. Глобальні та локальні змінні

8.8. Глобальні змінні

8.9. Локальні змінні

8.10. Зв’язок однойменних локальних і глобальних змінних

8.11. Нелокальні змінні

8.12. Правила локалізації

8.13. Lambda-функції

8.14. Рекурсія

8.15. Приклади розв’язування задач

8.16. Резюме

8.17. Питання для перевірки засвоєних знань

 

 

 

Уроки Python з нуля / #12 – Створення функцій (def, lambda)

 

Презентація. Функції в PYTHON №8

 

 

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

 

Функції в Python схожі на функції інших мов програмування. Це іменовані фрагменти коду, які можна викликати з будь-якого місця програми за їхнім ім’ям. Однак у Python є lambda-функції, які не мають імені. Загалом, функціяце частина коду, що працює відокремлено від іншої частини програми та викликається лише за потреби.

Функції ‒ дуже корисний інструмент програмування, оскільки дає змогу значно скоротити обсяг програмного коду, зробити його більш зрозумілим й результативним. Отже, без функцій писати ефективні програми практично нереально. Тому з функціями треба бути на «ти», особливо якщо йдеться про програмування мовою Python.

Раніше ми говорили про вбудовані функції у Python, як-от sqrt(), len(), print() тощо. Функції можуть приймати аргументи (нуль, один або кілька) і повертати значення. Наприклад, функція sqrt() обчислює квадратний корінь числа. Функція print() виводить різні значення, не повертаючи результат обчислень.

 

 

Створюючи власні функції, важливо уникати побічних ефектів, які відрізняються від основного призначення функції. Наприклад, якщо функція призначена для обчислень, не варто включати в неї операції виведення даних.

 

Нерідко розрізняють поняття параметра функції й аргументу функції. Про параметри, зазвичай, говорять під час опису функції. Про аргументи йдеться, коли вже описана функція викликається в програмному коді.

 

Опис функції складається із заголовка та тіла. У заголовку вказується ім’я та параметри функції, починаючи зі слова def і завершуючи двокрапкою. Тіло функції містить інструкції для виконання, з відступами відносно заголовка.

 

Формат опису функції:

def ім’я_функції(список формальних параметрів):

оператори тіла функції

 

Ім’я_функції це маркування, яке створюється відповідно до правил для ідентифікаторів і подальше використання для виклику функції.

 

Формальні параметри ‒ це назви змінних, які вказуються під час опису функції і через які передаються дані з основної програми в функцію. Значення для цих параметрів задаються під час виклику функції.

 

Список формальних параметрів подається у формі переліку імен змінних, розділених комами. Нагадаю, що у функції може і не бути формальних параметрів.

 

Проста функція, яка виводить привітання, матиме вигляд:

def func(name):

    print(‘Hello’,name)

 

У разі, якщо тіло функції має єдиний оператор, як у нашому випадку, то функцію можна записати одним рядком:

def funcs(name):

    print(‘Hello’, name)

 

Як можна бачити, ця функція має єдиний параметр name, який використовується як частина повідомлення для виведення на екран.

 

Для функції не зазначають тип результату (хоча функція, зрозуміло, може повертати результат). Це може стати сюрпризом для тих, хто вивчав і знайомий з іншими мовами програмування. Але це сюрприз тільки на перший погляд. Якщо згадати, що в мові Python для змінних тип не вказується і визначається за значенням, на яке посилається змінна, то все є цілком логічним: і відсутність ідентифікатора типу для результату функції, й аргументи, для яких тип теж не вказують.

 

Для виклику функції вказується її ім’я з указаним в дужках списком фактичних параметрів.

 

Формат оператора виклику функції:

ім’я_функції([список фактичних параметрів]);

Виклик раніше описаної функції матиме вигляд:

>>> func(‘World’)

Hello World

 

Викликати функцію можна тільки після того, як функцію оголошено, але ніяк не раніше.

 

Фактичні параметри визначаються як назви змінних або конкретні значення, які передаються під час виклику функції.

Перелік фактичних параметрів подається як перерахування, розділене комами.

Терміни «формальні параметри» і «фактичні параметри» іноді використовуються взаємозамінно. Формальні параметри можна називати параметрами функції, а фактичні аргументами функції. Вони не обов’язково повинні мати однакові імена.

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

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

Щоб функція повертала певне значення, її тіло має містити інструкцію return. Це ключове слово, за яким слідує значення або змінна, яке потрібно повернути з функції.

 

Наприклад, функція, за якою буде повернуто одиницю:

def one():

return 1

 

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

func(‘World’).

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

two= one()+one().

Проте варто зауважити, що у разі відсутності в тілі функції інструкції return, тобто не передбачення за функцією повернення ніякого значення, за функцією все одно буде повернуте значення None.

>>> def func(): print(‘Hello!’)

>>> print(func())

Hello!

None

Інколи виникає необхідність повернення за функцією не одного значення, а двох чи більше значень.

 

Для цього потрібно в інструкції return вказати список або кортеж з бажаної кількості значень:

def f1(a, b): return [a**2, b**2]

def f2(a, b): return (a**2, b**2)

Тоді виклик функції можна записати:

n1, m1 = f1(2, 3)

n2, m2 = f2(2, 3)

s1 = f1(2, 3)

s2 = f2(2, 3)

 

Після виклику та виконання функцій отримаємо таке: значення n1 та n2 будуть 4, m1 та m2 стануть 9, s1 міститиме список [4, 9], а s2 кортеж (4, 9). У функції може бути кілька інструкцій return, але значення, що повертається з функції, визначається першим використанням інструкції return.

Приклад. Написати функцію, за якою обчислюватиметься сума двох аргументів:

>>> def summa(a, b): return a+b

>>> summa(2, 3)

5

>>> x=5;

>>> y=6;

>>> summa(x, y)

11

Зважаючи на динамічну типізацію змінних в мові Python, аргументами однієї і тієї самої функції можуть бути значення чи змінні різного типу, наприклад:

>>> summa(‘Hello ‘,’world.’)

‘Hello world.’

>>> summa([2,3,4],[4,5,6])

[2, 3, 4, 4, 5, 6]

Проте за такого багатогранного використання функцій варто пам’ятати про чітку типізацію мови Python і неможливість проведення операцій у виразах з даними різних несумісних типів. Зокрема, наступний виклик функції summa(‘Hello ‘,5) призведе до виникнення винятку TypeError (unsupported operand type(s) for +: ‘intandstr).

 

 

Мова Python надає різноманітні можливості використання параметрів, як-от: встановлення початкових значень для параметрів; використання ключових аргументів, які можна вказати за їхніми назвами; створення функцій, які можуть приймати будь-яку кількість аргументів; визначення обов’язковості ключових аргументів.

 

 

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

 

Наприклад, у функції print() параметр sep часто не вказується, і в цьому разі для нього встановлюється початкове значення ‒ символ пропуску.

Це значення для параметра називається початковим значенням, і сам параметр стає необов’язковим.

 

Щоб вказати, що параметр матиме початкове значення, необхідно в описі функції після імені цього параметра поставити знак присвоєння (=) і вказати потрібне значення. Початкове значення має бути незмінним.

Наприклад:

>>> def summa(a, b=2): return a+b

>>> summa(4, 6)

10

>>> summa(4)

6

У першому випадку під час виклику функції вказано обидва аргументи (фактичні параметри), тому параметру a буде присвоєно значення 4, параметру b – 6 (їхня сума дорівнює 10). У другому випадку виклик функції містить лише один аргумент, отже, параметру a буде надане значення 4 (це перший параметр, тому йому присвоюється значення першого аргументу), а другому параметру початкове значення, яке дорівнює 2.

 

Передавання аргументів під час виклику функції можливе:

v без зазначення імені аргументів, при цьому значення аргументів передаються чітко в тій послідовності, як ці аргументи було описано у функції (такий спосіб передавання аргументів називають позиційним);

v  із явним зазначенням імені аргументів, при цьому порядок перерахування аргументів не має значення (такий спосіб називається передаванням аргумен­тів за ключем або за ім’ям, а самі аргументи іноді називають іменованими).

 

Якщо в аргументів деякої функції є початкове значення, то ця функція може викликатися з різною кількістю аргументів (подробиці залежать від специфіки опису функції). У мові Python можна оголошувати функції зі змінною кількістю аргументів. Це питання більш детально ми обговоримо пізніше. Тут же зробимо загальне вступне зауваження.

Припустімо, нам потрібно описати таку функцію, щоб її можна було викликати з різною кількістю аргументів. Важливо, що кількість аргументів не обмежена ми наперед не знаємо, скільки передаватиметься аргументів функції. У цьому разі ми описуємо функцію з одним аргументом, але перед цим аргументом ставимо зірочку *. Такий аргумент ототожнюється зі списком, елементи якого формуються реальними аргументами, переданими функції під час виклику. Інакше кажучи, наш «зірковий» аргумент у тілі функції оброблюється як список. Але під час виклику функції аргументи передаються, як звичайно.

У списку параметрів може бути будь-яка кількість параметрів із початковим значенням (типовим). Під час виклику функції значення переданих аргументів будуть присвоюватися параметрам функції послідовно. Це пов’язано з тим, що початкові аргументи мають позиційний характер значення аргументів привласнюються параметрам відповідно до їхньої позиції.

>>> def func(a, b=2, c=10):

    print(‘a=‘,a,’b=‘,b,’c=‘,c)

>>> func(3, 4, 5)

a= 3 b= 4 c= 5

>>> func(3, 4)

a= 3 b= 4 c= 10

>>> func(3)

a= 3 b= 2 c= 10

Параметри із початковим значенням у списку параметрів не можуть стояти перед параметрами без початкових значень. Це означає, що початкові значення можуть отримати лише параметри, розташовані в кінці списку параметрів.

Наприклад, уявімо функцію, описану так: def summa(a=2, b): return a+b. Якщо викликати її як summa(3), параметру «a», хоча й має початкове значення, буде присвоєно значення першого аргументу (тобто, 3), але для параметру «b» буде відсутнє значення аргументу, тому функція не буде викликана.

 

 

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

 

Ключовий аргумент ‒ це аргумент, який вказується з індикацією імені параметра, для якого він призначенийім’я_параметра = значення»).

 

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

Щоб встановити ключовий аргумент, необхідно вказати ім’я параметра, а потім через знак присвоєння вказати необхідне значення.

>>> def func(a, b=2, c=10):

    print(‘a=‘,a,’b=‘,b,’c=‘,c)

>>> func(3, c=15)

a= 3 b= 2 c= 15

>>> func(3, c=15, b=8)

a= 3 b= 8 c= 15

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

>>> func(c=22, a=23)

a= 23 b= 2 c= 22

 

Використання ключових аргументів має декілька переваг:

v по-перше, робить виклик функції простішим, оскільки не потрібно стежити за порядком аргументів;

v по-друге, дає змогу задавати значення тільки для певних параметрів, якщо решта параметрів мають початкові значення.

 

Але з’явилася можливість обмеження використання ключових аргументів у версії 3.8. Якщо поміж параметрами функції використати символ «/», то параметри перед ним стають лише позиційними, а ті, які йдуть після, можуть бути використані як ключові.

>>> def func(a, b=2, /, c=10):

    print(‘a=‘,a,’b=‘,b,’c=‘,c)

>>> func(3, 4, 5)

a= 3 b= 4 c= 5

>>> func(3, 4, c=5) a= 3 b= 4 c= 5

>>> func(3, b=4, c=5)

Traceback (most recent call last):

File «<pyshell#8>«, line 1, in <module>

   func(3, b=4, c=5)

TypeError: func() got some positional-only arguments

passed as keyword arguments: ‘b’

 

8.5. Змінна кількість аргументів

 

Іноді потрібно визначити функцію, яка здатна приймати будь-яку кількість аргументів, тобто змінну кількість аргументів. Наприклад, функція print() може приймати різну кількість значень для виведення, чи функція min() може приймати різну кількість значень для визначення мінімального серед них. Ця можливість здійснюється через те, що під час виклику функції змінна кількість аргументів збирається (упаковується) у кортеж або словник та передається в функцію.

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

Щоб вказати, що функція може приймати змінну кількість позиційних аргументів, під час її опису необхідно вказати параметр, перед яким стоїть знак «*».

Наприклад, для функції:

def summa(first=0, *param):

    print(‘first=‘, first, ‘; param=‘, param, sep=‘‘)

    s=first

    for number in param:

        s+=number

    return s

можливі різні варіанти її виклику:

>>> print(‘summa=‘, summa())

first=0; param=()

summa= 0

>>> print(‘summa=‘, summa(5,3,4))

first=5; param=(3, 4)

summa= 12

>>> print(‘summa=‘, summa(5,3,4,5,6,7,8))

first=5; param=(3, 4, 5, 6, 7, 8)

summa= 38

 

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

Щоб вказати, що функція може приймати змінну кількість ключових аргументів, під час її опису необхідно вказати параметр, перед яким ставлять два знаки «**». Наприклад, для функції:

def summa(first=0, **param):

    print(‘first=‘, first, ‘; param=‘, param, sep=‘‘)

    s=first

    for key in param:

        s+=param[key]

   return s

можливі різні варіанти її виклику:

>>> print(‘summa=‘, summa(2, s1=3, s2=4))

first=2; param={‘s1’: 3, ‘s2’: 4}

summa= 9

>>> print(‘summa=‘, summa(s1=3, s2=4))

first=0; param={‘s1’: 3, ‘s2’: 4}

summa= 7

 

Отже, можна помітити, що всі ключові аргументи, починаючи з другого, збираються в словник із назвою param.

Розглянуті випадки можуть бути використані одночасно:

def summa(first=0, *param1, **param2):

    print(‘first=‘, first)

    print(‘param1=‘, param1)

    print(‘param2=‘, param2)

    s=first

    for number in param1:

        s+=number

    for key in param2:

        s+=param2[key]

    return s

>>> print(‘summa=‘, summa(3,4,5,6))

first= 3

param1= (4, 5, 6)

param2= {}

summa= 18

>>> print(‘summa=‘, summa(s1=3, s2=4))

first= 0

param1= ()

param2= {‘s1’: 3, ‘s2’: 4}

summa= 7

>>> print(‘summa=‘, summa(3,4,5,6,s1=3, s2=4))

first= 3

param1= (4, 5, 6)

param2= {‘s1’: 3, ‘s2’: 4}

summa= 25

 

8.6. Обовязкові ключові аргументи

 

Іноді потрібно описувати функції так, що певні параметри будуть доступні лише за допомогою ключових аргументів, що сприятиме більшій зрозумілості їхнього використання. Наприклад, у функції print() є параметри sep та end, значення для яких можна вказати, тільки використовуючи ключові аргументи.

Щоб визначити параметр, який може приймати значення тільки через ключовий аргумент, його необхідно оголосити після параметра із зірочкою (параметра, який прийматиме змінну кількість аргументів).

def summa(first=0, *param, mult):

   print(‘first=‘, first, ‘; param=‘, param, sep=‘‘)

   print(mult=‘, mult)

   s=first

   for number in param:

       s+=number

   s*=mult

   return s

>>> print(‘result=‘, summa(1,2,3, mult=5))

first=1; param=(2, 3)

mult= 5

result= 30

>>> print(‘result=‘, summa(1,2,3,5))

Якщо ми виконаємо оператор print(‘result=‘, summa(1, 2, 3, 5)), отримаємо помилку через те, що параметру mult не буде надано значення, оскільки всі аргументи, починаючи з другого, збираються в кортежі param.

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

def summa(first=0, *, mnog):

 

 

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

 

У мовах програмування, як-от C++ і Java, де змінні оголошують із зазначенням типу, проблем із розподілом змінних на локальні та глобальні не виникає. Цю класифікацію легко провести на підставі того, де, в якому місці програмного коду змінну оголошено. У мові Python ситуація складніша. Річ у тім, що оскільки змінні в Python заздалегідь (до першого використання) не оголошують, то визначити, яка змінна локальна, а яка – глобальна, не так уже й просто.

 

8.8. Глобальні змінні

 

Всередині функції можуть бути використані змінні, оголошені в основній програмі. Наприклад, маємо програму:

def f():

    print(Z)

Z = 1

f()

Під час виконання цієї програми на екрані буде виведено число 1. Перед тим як функція f() буде викликана, змінній Z присвоюється значення 1. Тому, коли функція викликається, Z вже має значення, і значення цієї змінної виводиться за допомогою оператора print(Z).

 

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

 

 

Якщо змінна ініціалізується всередині функції, вона буде доступна лише всередині цієї функції. Використання такої змінної поза межами функції буде неприпустимим. Наприклад, маємо програму:

def f():

      Z = 1

f() print(Z)

Як результат виконання такої програми отримаємо виняток:

NameError: name ‘Z’ is not defined.

Змінні, які оголошені всередині функції або вказані у списку параметрів цієї функції, називають локальними.

Поза межами функції ці локальні змінні не доступні. Це обмеження дає змогу використовувати змінні з однаковим ім’ям у різних функціях.

 

 

У процесі написання програми може виникнути ситуація, коли у програмі з’являться змінні з однаковими іменами, які мають локальну та глобальну області видимості. У такому разі може виникнути питання про те, яким чином оброблятимуться та взаємодіятимуть локальні та глобальні змінні за зміни їх значень.

Наприклад, маємо програму:

def func():

    Z=2

print(‘Z всередині функції =‘, Z)

Z=5

func()

print(‘Z за межами функції=‘, Z)

Після її виконання отримаємо:

Z всередині функції= 2 Z за межами функції= 5

Незважаючи на те, що значення змінної Z було змінено всередині функції, за межами функції воно залишилося незміненим. Це пояснюється тим, що під час виконання функції func() було створено та ініціалізовано локальну змінну Z, областю видимості якої стало лише тіло функції. Отже, зміна значення локальної змінної Z не вплинула на значення глобальної змінної Z. Це забезпечує «захист» глобальних змінних від ненавмисних змін в тілі функції.

Якщо в тілі функції відбувається зміна значення певної змінної, то ця змінна стає локальною, і її зміна не впливає на значення глобальної змінної з аналогічним ім’ям. Формально це можна сформулювати так: інтерпретатор Python вважає змінну локальною для цієї функції, якщо в тілі функції є хоча б одна інструкція, яка змінює значення цієї змінної. Оператор присвоєння «=» або використання змінної як параметра циклу for може бути інструкцією, яка модифікує значення змінної.

Щодо зміни значень глобальних змінних у функції, іноді виникає необхідність використовувати таку можливість. Для забезпечення змоги змінювати значення глобальної змінної всередині функції, слід оголосити цю змінну в тілі функції за допомогою ключового слова global:

def func():

    global Z

    print(‘Z в середині функції (до зміни) =‘, Z)

    Z=2

    print(‘Z в середині функції (після зміни) =‘, Z)

Z=5

func()

print(‘Z за межами функції =‘, Z)

Після виконання отримаємо:

Z в середині функції (до зміни) = 5

Z в середині функції (після зміни) = 2

Z за межами функції = 2

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

 

 

Є ще один тип змінних, які називають «нелокальними» (nonlocal).

 

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

def func():

    Z=2

    print(‘Z в середині функції (до зміни) =‘, Z)

    def func1():

        nonlocal Z

        Z=3

    func1()

    print(‘Z в середині функції (після зміни) =‘, Z)

Z=5

func()

print(‘Z за межами функції =‘, Z)

Опис нелокальної змінної nonlocal Z всередині функції func1() означає, що областю видимості цієї змінної є не тіло функції func1(), а тіло функції func().

Після виконання отримаємо:

Z в середині функції (до зміни) = 2

Z в середині функції (після зміни) = 3

Z за межами функції = 5

Якщо ж в тілі функції func1() буде відсутній оператор nonlocal Z, то матимемо: глобальну змінну Z, локальну змінну Z для функції func() та локальну змінну Z для функції func1(), тобто три окремі незалежні змінні.

 

 

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

Щоб коректно використовувати змінні, важливо враховувати такі правила відносно їх ідентифікаторів.

v Кожен ідентифікатор має бути присвоєний значенням перед його використанням.

v Область дії ідентифікатора обмежена блоком, у якому він був оголошений.

v У кожному блоці всі ідентифікатори мають бути унікальними, тобто не повторюватися.

v Той самий ідентифікатор може мати різне значення в різних блоках програми.

 

8.13. Lambda функції

 

Використання ключового слова «def» дає змогу описувати функції з іменем, які можна викликати з будь-якого місця програми.

 

Окрім цього, мова Python підтримує lambda-функції, які є безіменними та іноді називають анонімними.

 

Lambda-функція містить лише один оператор, завжди повертає значення, яке можна призначити змінній. Ця змінна дає змогу звертатися до функції (зворотний виклик) з будь-якої точки програми. Використання lambda-функцій відкриває можливість програмістам використовувати альтернативний синтаксис для створення функцій.

Наприклад функцію:

def sqrt(x): return x ** 0.5

можна записати так:

sqrt = lambda x: x ** 0.5

В обох випадках виклик sqrt(25) поверне результат 5.0.

Lambda-функції часто використовуються для вбудовування функціоналу в будь-яке місце коду. Наприклад, їх часто використовують у функціях map(), filter(), reduce(), де вони застосовуються до списків.

 

Наприклад, функція map приймає два параметри: перший ‒ це функція, яка буде застосована до кожного елементу списку, а другий ‒ сам список, який має бути опрацьований.

>>> m=[1,2,3,4,5,6,7]

>>> list(map(lambda x: x*3, m))

[3, 6, 9, 12, 15, 18, 21]

Іншим прикладом використання lambda-функцій є вбудовування таких функцій безпосередньо в список аргументів:

>>> funcs = [lambda x : x**2, lambda x : x**3, lambda x : x**4]

>>> for func in funcs : print(‘Result:’, func(3))

Result: 9

Result: 27

Result: 81

 

8.14. Рекурсія

 

Функція може викликати іншу функцію, а також сама себе. Цей процес виклику функцією самої себе називається рекурсією. Коли функція містить виклик самої себе, її називають рекурсивною.

 

Розгляньмо приклад використання рекурсії через функції обчислення факторіала та цілих степенів числа.

Формула обчислення факторіала:

n!=1, якщо n=0; n!=n*(n–1)!, якщо n>0.

Формула обчислення цілого степеня числа:

xn=1, якщо n=0; xn=x*xn-1, якщо n>0.

 

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

def factorial(n):

    if n == 0:

       return 1

    else:

      return n * factorial(n-1)

def intPower(x, n):

    if n == 0:

       return 1

    else:

       return x * intPower (x, n-1)

Рекурсивні функції є потужним інструментом у програмуванні, проте не завжди ефективним з погляду використання пам’яті. Кожен новий виклик такої функції вимагає виділення пам’яті для зберігання локальних змінних.

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

 

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

 

 

Приклад. Використання вкладених функцій.

# Зовнішня функція

def sq_sum():

# Вкладена функція для зчитування

# кількості доданків

def get_n():

# Зчитуємо числове значення

n=int(input("Доданків у сумі:"))

# Результат функції get_n() ціле число

return n

# Вкладена функція для обчислення

# суми квадратів натуральних чисел.

# Результатом є функція

def find_sq_sum():

# Початкове значення суми

s=0

# Оператор циклу для обчислення суми

for i in range(1,n+1):

s+=i**2 # Новий доданок у сумі

# Результат функції find_sq_sum()

return s

# Визначаємо кількість доданків у сумі

n=get_n()

# Результат функції sq_sum() вкладена функція

return find_sq_sum

# Обчислюємо суму квадратів чисел

z=sq_sum()()

# Відображаємо результат

print(ʺСума квадратів дорівнює:ʺ,z)

Результат виконання програми

Доданків у сумі: 10

Сума квадратів дорівнює: 385

 

Приклад. Написати програму, за якою обчислюватиметься площа трикутника, заданого довжинами його сторін.

import math

def geron(a,b,c):

    p=(a+b+c)/2

    return math.sqrt(p*(p-a)*(p-b)*(p-c))

print(‘Введіть довжини сторін трикутника:’)

a=float(input())

b=float(input())

c=float(input())

if a+b>c and a+c>b and b+c>a:

   s=geron(a,b,c)

   print(‘Площа трикутника =‘, s)

else:

   print(‘Трикутник з даними сторонами не існує.’)

 

Приклад. Обчислити значення виразу

f(x)=x2+x+3+ex2+x+3+sin2(x2+x+3) x=1,2,…,10.

import math

def y(x):

    return x*x+x+3

for i in range(1,11):

    f=y(i)+ math.pow(math.e,y(i)) +

    math.pow(math.sin(y(i)),2)

    print(‘f({})={}’.format(i,f))

 

Приклад. Знайти довжину вектора, заданого своїми координатами у n – вимірному просторі.

import math

def vLength(v, n):

    s=0

    for i in range(n):

        s+=v[i]**2;

   return math.sqrt(s)

n=int(input(‘Введіть кількість елементів списку = ‘))

a=[]

for i in range(1,n+1):

     x=int(input(‘a[{}]=‘.format(i)))

     a.append(x)

print(‘Довжина вектора a=‘,vLength(a,n));

 

Приклад. Дано a,b,cдовжини сторін деякого трикутника. Знайти медіани трикутника.

Довжина медіани, проведеної до сторони а, дорівнює:

import math

def median(x,y,z):

    return 0.5*math.sqrt(2*x*x+2*y*y-z*z)

print(‘Введіть довжини сторін трикутника:’)

a=float(input())

b=float(input())

c=float(input())

if a+b>c and a+c>b and b+c>a:

   m1=median(a,b,c)

   m2=median(a,c,b)

   m3=median(c,b,a)

   print(‘Медіана 1 =‘, m1)

   print(‘Медіана 2 =‘, m2)

   print(‘Медіана 3 =‘, m3)

else:

   print(‘Трикутник з даними сторонами не існує.’)

 

Приклад. Дано цілочисельну матрицю випадкових цілих чисел розміром m´n (m і n задається користувачем). Знайти мінімальний елемент матриці. Описати функції генерування матриці, виведення матриці та функцію пошуку мінімального елементу.

import random

def gener_matr(n,m):

    a=[]

    for i in range(n):

       b=[]

       for j in range(m):

           x=random.randint(10,99)

          b.append(x)

     a.append(b)

  return a

def print_matr(a):

    print(‘Згенерована матриця:’)

    for row in a:

        for elem in row:

            print(elem, end=‘ ‘)

        print()

def min_matr(a):

    min_col=list(map(min, a))

    min_el=min(min_col)

   return min_el

n=int(input(‘Введіть кількість рядків матриці: ‘))

m=int(input(‘Введіть кількість стовпців матриці: ‘))

a=gener_matr(n,m)

print_matr(a)

print(‘Мінімальний елемент: ‘,min_matr(a))

 

Завдання для самоперевірки

Завдання 1. Задача про трикутник.

Трикутник задано координатами вершин А(0; 0), В(і; і-1) та С(-і; і+1),

де і – порядковий номер у списку.

Варіанти:

1. Обчислити висоту ha та бісектрису Wc.

2. Обчислити медіану mа та бісектрису Wb.

3. Обчислити бісектрису Wa та радіус вписаного кола r.

4. Обчислити висоту ha та медіану ть..

 

Завдання 2. Використати функції для обрахунку:

 

 

Ø В описі функції використовують ідентифікатор def, після якого вказують ім’я функції, список аргументів (у круглих дужках) і після двокрапки програмний код функції.

Ø Інструкція return у тілі функції закінчує виконання програмного коду функції, а значення, вказане після інструкції return, повертається як результат функції.

Ø Кожній функції відповідає об’єкт типу function. Ім’я функції є посиланням на об’єкт функції. Посилання на об’єкт функції може бути присвоєне змінній. У цьому разі змінна буде посиланням на функцію, і ця змінна може бути використана як ім’я функції.

Ø Ім’я функції може передаватися аргументом іншій функції.

Ø Функція може повертати як результат функцію. У цьому разі повертається посилання на функцію-результат.

Ø В аргументів можуть бути початкові значення. Початкові значення аргументів указують через знак рівності після імені аргументів. Аргументи із початковими значеннями указують у списку аргументів функції останніми.

Ø В опису функції в тілі функції можна викликати описувану функцію (звичайно, з іншими аргументами). Така ситуація називається рекурсією.

Ø Лямбда-функція або анонімна функція це функція без імені. Такі функції можна, наприклад, передавати аргументом в інші функції або повертати результатом функції. Описують лямбда-функцію за допомогою ключового слова lambda, після якого вказують аргументи і через двокрапку вираз, який є результатом лямбда-функції.

Ø Якщо змінній присвоєно значення в тілі функції, то така змінна є локальною. Вона доступна лише в тілі функції. Якщо змінна в тілі функції входить у вирази, але значення їй не присвоюється, то така змінна глобальна. Щоб явно задекларувати змінну в тілі функції, як глобальну, використовують ключове слово global.

Ø У тілі функції можуть бути описані й інші функції. Такі функції називають вкладеними. Вкладені функції мають доступ до змінних у тілі зовнішньої функції.

 

Питання для перевірки засвоєних знань

1. Що таке функція в програмуванні?

2. Як оголосити функцію в Python?

3. Що таке параметри та аргументи функції?

4. Які можливості повернення значень мають функції в Python?

5. Які переваги використання функцій для структурування коду?

6. Як викликати функцію у Python?

7. Які різновиди аргументів можна передавати у функцію?

8. Що таке анонімні функції у Python?

9. Які є вбудовані функції в Python і як їх використовувати?

10. Що таке область видимості змінних у функціях і чому вона важлива?

11. Що таке позиційні аргументи в функціях?

12. Які переваги мають іменовані аргументи у функціях?

13. Як можна передавати змінну кількість аргументів у функцію?

14. Що таке початкове значення для аргументів у функціях?

15. Які прийоми використовуються для обробки необов’язкових аргументів у функціях?

16. Які обмеження можуть бути пов’язані з використанням аргументів з початковим значенням?

17. Що таке ключові аргументи в функціях Python?

18. Як ви можете визначити порядок аргументів у функції, використовуючи іменовані та позиційні аргументи?

19. Які прийоми є для передавання змінних аргументів у функцію?

20. Що таке рекурсивні функції та як вони можуть використовувати аргументи?

Попередня тема

На початок

Наступна тема