|
|
Програмування мовою Python: основи та практика Електронний посібник |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
У роботі з програмуванням часто трапляється
так, що одну й ту саму групу операторів, що виконують певну частину завдання,
потрібно використовувати у різних місцях програми. Щоб уникнути цього,
застосовують концепцію підпрограм, яка поширена у більшості мов
програмування. Наприклад, у Pascal це можуть бути процедури чи функції, у C
та Python ‒ функції.
Створюючи власні функції, важливо
уникати побічних ефектів, які відрізняються від основного призначення функції.
Наприклад, якщо функція призначена для обчислень, не варто включати в неї
операції виведення даних.
Опис функції складається із заголовка
та тіла. У заголовку вказується ім’я
та параметри функції, починаючи зі слова def і завершуючи двокрапкою. Тіло
функції містить інструкції для виконання, з відступами відносно заголовка.
Список формальних параметрів
подається у формі переліку імен змінних, розділених комами. Нагадаю, що у
функції може і не бути формальних параметрів.
Як можна бачити, ця функція
має єдиний параметр name, який використовується
як частина повідомлення для виведення на екран.
Для виклику функції вказується її ім’я
з указаним в дужках списком фактичних параметрів.
Фактичні параметри визначаються як
назви змінних або конкретні значення, які передаються під час виклику
функції. Перелік фактичних параметрів
подається як перерахування, розділене комами. Терміни «формальні параметри» і «фактичні параметри» іноді використовуються взаємозамінно. Формальні параметри можна називати
параметрами функції, а фактичні ‒ аргументами
функції. Вони не обов’язково повинні мати однакові імена. Загалом, кількість фактичних
параметрів має відповідати кількості формальних параметрів. Це важливо для
встановлення відповідності між ними під час виклику функції. У Python також є особливості співставлення цих
параметрів, які розглядатимуться пізніше. Використання параметрів у функціях
дає змогу розробнику зробити їх більш гнучкими та універсальними. Параметри
можуть бути вхідними або допоміжними даними, які використовуються в обчисленнях,
передбачених функцією. Щоб функція
повертала певне значення, її тіло має містити
інструкцію return. Це ключове слово, за яким
слідує значення або змінна, яке потрібно повернути з функції.
Якщо за функцією не передбачено повернення
ніяких значень, функція може викликатися у головній програмі чи іншій функції
як окремий оператор:
Якщо за функцією передбачене повернення
певного значення, то функція може викликатися у головній програмі чи іншій
функції як операнд виразу:
Проте варто зауважити,
що у разі відсутності в тілі функції інструкції return, тобто не передбачення за функцією повернення ніякого
значення, за функцією все одно буде повернуте значення None.
Інколи виникає необхідність
повернення за функцією не одного значення, а двох чи більше значень.
Після виклику та виконання функцій
отримаємо таке: значення n1 та n2 будуть 4,
m1 та m2
стануть 9, s1 міститиме список [4, 9], а s2 ‒ кортеж (4,
9). У функції може бути кілька інструкцій return, але значення, що повертається з функції, визначається першим використанням
інструкції return. Приклад. Написати функцію, за якою
обчислюватиметься сума двох аргументів:
Зважаючи на динамічну типізацію змінних в мові Python, аргументами однієї і тієї самої функції можуть бути значення чи змінні різного типу, наприклад:
Проте за такого багатогранного
використання функцій варто пам’ятати про чітку типізацію мови Python і неможливість проведення операцій у виразах з даними різних несумісних типів. Зокрема, наступний виклик функції summa(‘Hello ‘,5) призведе до виникнення винятку TypeError (unsupported operand type(s)
for +: ‘int’ and ‘str’). Мова Python надає різноманітні можливості використання параметрів, як-от:
встановлення початкових значень для параметрів; використання ключових
аргументів, які можна вказати за їхніми назвами; створення функцій, які
можуть приймати будь-яку кількість аргументів; визначення обов’язковості
ключових аргументів. Під час написання опису функцій часом
виникає ситуація, коли певний параметр здебільшого матиме одне значення під час
виклику функції. Проте є випадки, коли цей параметр може мати різне значення
за різних викликів цієї самої функції.
Щоб вказати, що параметр матиме
початкове значення, необхідно в описі функції після імені цього параметра
поставити знак присвоєння (=) і
вказати потрібне значення. Початкове значення має бути незмінним. Наприклад:
У першому випадку під час виклику функції вказано обидва аргументи (фактичні параметри), тому параметру a буде присвоєно значення 4, параметру b – 6 (їхня сума дорівнює 10). У другому випадку
виклик функції містить лише один аргумент, отже, параметру a буде надане
значення 4 (це перший параметр,
тому йому присвоюється значення першого аргументу), а другому параметру ‒ початкове значення, яке дорівнює 2.
Якщо в аргументів
деякої функції є початкове значення, то ця функція може викликатися з різною
кількістю аргументів (подробиці залежать від специфіки опису функції).
У мові Python можна оголошувати функції зі змінною кількістю
аргументів. Це питання більш детально ми обговоримо пізніше. Тут же зробимо
загальне вступне зауваження. Припустімо,
нам потрібно описати таку функцію, щоб її можна було викликати з різною
кількістю аргументів. Важливо, що кількість аргументів не обмежена ‒ ми наперед не знаємо, скільки передаватиметься аргументів функції. У цьому
разі ми описуємо функцію з одним аргументом, але перед цим аргументом ставимо зірочку *. Такий аргумент ототожнюється зі списком,
елементи якого формуються реальними аргументами, переданими функції під час
виклику. Інакше кажучи, наш «зірковий» аргумент у тілі функції оброблюється як список. Але під час виклику функції
аргументи передаються, як звичайно. У списку параметрів може бути
будь-яка кількість параметрів із початковим значенням (типовим). Під час
виклику функції значення переданих аргументів будуть присвоюватися параметрам
функції послідовно. Це пов’язано з тим, що початкові аргументи мають
позиційний характер ‒ значення
аргументів привласнюються параметрам відповідно до їхньої позиції.
Параметри із початковим значенням у списку параметрів не можуть стояти перед
параметрами без початкових значень. Це означає, що початкові значення можуть
отримати лише параметри, розташовані в кінці списку параметрів. Наприклад, уявімо функцію,
описану так: def summa(a=2, b): return a+b. Якщо викликати її як summa(3), параметру «a», хоча й має початкове
значення, буде присвоєно значення першого аргументу (тобто, 3), але для параметру «b» буде відсутнє значення аргументу, тому функція
не буде викликана. З-поміж позиційних аргументів, коли значення параметрів встановлюються відповідно до послідовності аргументів, у мові Python є можливість використовувати ключові аргументи.
Наприклад, у функції можуть бути параметри
із початковими значеннями. Але під час виклику цієї функції може бути
потрібно вказати значення лише для певних параметрів. В такому разі
використання ключових аргументів стане в пригоді. Під час виклику функції
можна буде задати значення лише для тих параметрів, для яких не підходять їх
початкове значення. Щоб встановити ключовий аргумент,
необхідно вказати ім’я параметра, а потім через знак присвоєння вказати
необхідне значення.
Аргумент може
бути ключовим не лише для параметра із початковим
значенням. Проте в цьому разі такий ключовий аргумент має обов’язково бути
під час виклику функції.
Але з’явилася можливість обмеження
використання ключових аргументів у версії 3.8. Якщо поміж параметрами функції
використати символ «/», то
параметри перед ним стають лише позиційними, а ті, які йдуть після, можуть
бути використані як ключові.
Іноді потрібно визначити функцію, яка здатна приймати будь-яку кількість аргументів, тобто змінну кількість аргументів. Наприклад, функція print() може приймати різну кількість значень для виведення, чи функція min() може приймати різну кількість значень для визначення
мінімального серед них. Ця можливість здійснюється через те, що під час
виклику функції змінна кількість аргументів збирається (упаковується) у
кортеж або словник та передається в функцію. Змінна кількість аргументів може
використовуватися як для позиційних, так і для ключових аргументів. Крім
того, під час опису функції можуть бути параметри як для одиночних
аргументів, так і для змінної кількості, важливо лише, щоб опис параметрів
для одиночних аргументів передував опису параметрів для змінної кількості
аргументів. Щоб вказати, що функція може приймати
змінну кількість позиційних аргументів, під час її опису необхідно вказати
параметр, перед яким стоїть знак «*». Наприклад, для функції:
Отже, можна помітити, що всі
позиційні аргументи, починаючи з другого, збираються в кортеж під назвою param. Щоб вказати, що функція може приймати
змінну кількість ключових аргументів, під час її опису необхідно вказати
параметр, перед яким ставлять два знаки «**».
Наприклад, для функції:
Отже, можна помітити, що всі ключові аргументи, починаючи
з другого, збираються в словник із
назвою param. Розглянуті випадки
можуть бути використані одночасно:
Іноді потрібно описувати функції так, що певні параметри будуть доступні лише за допомогою ключових аргументів, що сприятиме більшій зрозумілості їхнього використання. Наприклад, у функції
print() є параметри sep
та end, значення для яких можна вказати, тільки
використовуючи ключові аргументи. Щоб визначити параметр, який може
приймати значення тільки через ключовий аргумент, його необхідно оголосити
після параметра із зірочкою (параметра, який прийматиме змінну кількість
аргументів).
Якщо ми виконаємо оператор print(‘result=‘, summa(1, 2, 3, 5)), отримаємо помилку через те, що параметру mult не буде надано значення, оскільки всі аргументи, починаючи з другого, збираються в кортежі param. Якщо функція не передбачає наявність змінної кількості аргументів, але
потрібно мати параметр лише через ключові аргументи, заголовок такої функції
можна визначити так:
Кожна змінна має свій власний
контекст видимості, що визначається блоком, в якому вона була оголошена і діє
з моменту оголошення до кінця цього блоку. Під час використання функцій у
програмі змінні та пов’язані з ними дані розділяються на глобальні та
локальні через цей механізм.
Всередині функції можуть бути
використані змінні, оголошені в основній програмі. Наприклад, маємо програму:
Під час виконання цієї програми на
екрані буде виведено число 1. Перед
тим як функція f() буде викликана, змінній Z присвоюється значення 1. Тому, коли функція викликається, Z вже має значення, і значення
цієї змінної виводиться за допомогою
оператора print(Z).
Якщо змінна ініціалізується всередині функції, вона буде доступна
лише всередині цієї функції. Використання такої змінної поза межами функції
буде неприпустимим. Наприклад, маємо програму:
Змінні, які оголошені всередині функції або вказані у списку параметрів цієї функції, називають локальними. Поза межами функції
ці локальні змінні не доступні. Це обмеження дає змогу
використовувати змінні з однаковим ім’ям у різних функціях. У процесі написання програми може
виникнути ситуація, коли у програмі з’являться змінні з однаковими іменами,
які мають локальну та глобальну області видимості. У такому разі може
виникнути питання про те, яким чином оброблятимуться та взаємодіятимуть
локальні та глобальні змінні за зміни їх значень. Наприклад, маємо
програму:
Незважаючи на те, що значення змінної
Z було змінено всередині функції, за
межами функції воно залишилося незміненим. Це пояснюється тим, що під час виконання
функції func() було створено та ініціалізовано локальну змінну Z,
областю видимості якої стало лише тіло функції. Отже, зміна значення
локальної змінної Z не вплинула на
значення глобальної змінної Z. Це
забезпечує «захист» глобальних змінних від ненавмисних змін в тілі функції. Якщо в тілі функції відбувається
зміна значення певної змінної, то ця змінна стає локальною, і її зміна не
впливає на значення глобальної змінної з аналогічним ім’ям. Формально це можна сформулювати
так: інтерпретатор Python
вважає змінну локальною
для цієї функції, якщо в тілі функції є хоча б одна інструкція, яка змінює
значення цієї змінної. Оператор присвоєння «=»
або використання змінної як параметра циклу for може бути інструкцією, яка модифікує значення змінної. Щодо зміни значень глобальних змінних
у функції, іноді виникає необхідність використовувати таку можливість. Для
забезпечення змоги змінювати значення глобальної змінної всередині функції,
слід оголосити цю змінну
в тілі функції за допомогою ключового слова global:
Здебільшого краще уникати зміни
значень глобальних змінних всередині функції. Якщо функція потребує зміни
значення змінної, краще повернути це значення функцією, а саму операцію зміни
виконати у головній програмі. За виконання цього правила функції стають більш
незалежними від коду головної програми, і їх можна легко переносити з однієї
програми в іншу.
Вони утворюють певний перехідний тип
між локальними та глобальними змінними. Такі змінні, зазвичай, з’являються у
функціях, що визначені всередині інших функцій. Для оголошення змінної, яка є
нелокальною, використовується ключове
слово nonlocal.
Опис нелокальної змінної nonlocal Z всередині функції func1() означає, що областю видимості цієї змінної є не тіло функції func1(), а тіло функції func(). Після виконання отримаємо:
Якщо ж в тілі
функції func1()
буде відсутній оператор nonlocal
Z, то матимемо: глобальну
змінну Z,
локальну змінну Z для функції func() та локальну змінну Z для функції func1(), тобто три окремі
незалежні змінні. Програми мовою Python мають модульну структуру, в якій блоки можуть бути вкладені один в одного, утворюючи ланцюжок
функцій. Головна програма становить найвищий рівень. Змінні, описані на рівні
головної програми, є глобальними і доступними у всіх вкладених блоках. У
внутрішніх блоках оголошені змінні є локальними і не доступними за їх межами. Щоб коректно використовувати змінні, важливо враховувати такі правила
відносно їх ідентифікаторів. v Кожен
ідентифікатор має бути присвоєний значенням перед його використанням. v Область дії
ідентифікатора обмежена блоком, у якому він був оголошений. v У кожному
блоці всі ідентифікатори мають бути унікальними, тобто не повторюватися. v Той самий
ідентифікатор може мати різне значення в різних блоках програми.
Використання ключового слова «def» дає змогу описувати
функції з іменем, які можна викликати з будь-якого
місця програми.
Lambda-функція містить лише
один оператор, завжди повертає значення, яке можна призначити змінній. Ця
змінна дає змогу звертатися до функції (зворотний виклик) з будь-якої точки
програми. Використання lambda-функцій відкриває можливість
програмістам використовувати
альтернативний синтаксис для створення функцій. Наприклад функцію:
В обох випадках виклик sqrt(25) поверне результат 5.0. Lambda-функції часто використовуються
для вбудовування функціоналу в будь-яке місце коду. Наприклад,
їх часто використовують у
функціях map(),
filter(), reduce(), де вони застосовуються до списків.
З формул бачимо, що для обчислення
кожного наступного значення треба знати попереднє. Розгляньмо
реалізацію функцій обчислення факторіала і цілого степеня числа.
Рекурсивні функції є потужним інструментом
у програмуванні, проте не завжди ефективним з погляду використання пам’яті.
Кожен новий виклик такої функції вимагає виділення пам’яті для зберігання
локальних змінних. Додатково, неправильно розроблена
рекурсивна функція може призвести до безкінечного циклу викликів, де
послідовність викликів функції ніколи не завершується, і це може
продовжуватися, доки не буде використана вся доступна пам’ять у комп’ютері.
Отже, для правильної роботи рекурсивних функцій необхідно наявність умови
завершення рекурсії, наприклад, перевірка значення параметра, що змінюється.
# Зовнішня
функція 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(‘Трикутник з даними сторонами не існує.’)
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))
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));
Довжина
медіани, проведеної до сторони а, дорівнює:
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(‘Трикутник з даними сторонами не існує.’)
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))
Ø В описі функції використовують ідентифікатор def, після якого вказують
ім’я функції, список аргументів (у круглих дужках) і після двокрапки
програмний код функції. Ø Інструкція return у тілі
функції закінчує виконання програмного коду функції, а значення, вказане після інструкції return, повертається
як результат функції. Ø Кожній функції
відповідає об’єкт типу function. Ім’я
функції є посиланням на об’єкт
функції. Посилання на об’єкт функції може бути присвоєне змінній.
У цьому разі змінна буде посиланням на функцію, і ця змінна може бути
використана як ім’я функції. Ø Ім’я функції може передаватися аргументом іншій функції. Ø Функція може повертати як результат функцію. У цьому разі повертається посилання на
функцію-результат. Ø В аргументів можуть бути початкові значення. Початкові значення
аргументів указують через знак рівності після імені аргументів. Аргументи із
початковими значеннями указують у списку аргументів функції останніми. Ø В опису функції в тілі функції можна викликати описувану функцію (звичайно, з іншими
аргументами). Така ситуація називається рекурсією. Ø Лямбда-функція або анонімна функція
‒ це функція без імені. Такі
функції можна, наприклад, передавати аргументом в інші функції або повертати
результатом функції. Описують лямбда-функцію
за допомогою ключового
слова lambda, після якого вказують
аргументи і через двокрапку вираз, який є
результатом лямбда-функції. Ø Якщо змінній присвоєно значення в тілі функції, то така змінна є
локальною. Вона доступна лише в тілі функції. Якщо змінна в тілі функції
входить у вирази, але значення їй не присвоюється, то така змінна ‒ глобальна. Щоб явно задекларувати змінну в тілі
функції, як глобальну, використовують ключове слово global. Ø У тілі функції можуть бути описані й інші функції. Такі функції
називають вкладеними. Вкладені
функції мають доступ до змінних у тілі зовнішньої
функції.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||