Вкладені функції. Вкладені області видимості. Правила пошуку імен у випадку вкладених функцій. Фабричні функції. Передача значень у вкладену функцію
Зміст
- 1. Що таке вкладені функції?
- 2. Правила пошуку імен всередині функції у випадку вкладених областей видимості
- 3. Приклади вкладених функцій
- 4. Фабричні функції. Основні поняття. Приклад
- 5. Передача даних з охоплюючої області видимості у вкладену функцію з допомогою аргументів за замовчуванням. Приклад
- Зв’язані теми
Пошук на інших ресурсах:
1. Що таке вкладені функції?
У мові програмування Python можуть використовуватись вкладені функції. Це означає, що всередині інструкції def може бути інша інструкція def. Кількість вкладень функцій довільна. В найбільш загальному випадку форма оголошення вкладених функцій наступна:
def Fn_1(parameters1): ... def Fn_2(parameters2): ... def Fn_N(parametersN): ... return ... return return
тут
- Fn_1, Fn_2, Fn_N – імена функцій, що відповідно отримують параметри parameters1, parameters2, parametersN.
⇑
2. Правила пошуку імен всередині функції у випадку вкладених областей видимості
Якщо всередині функції, яка є вкладеною в іншу функцію, оголошено ім’я (змінну) то діють наступні правила:
1. У випадку звертання до імені пошук цього імені здійснюється в наступній послідовності:
- пошук в локальній області видимості;
- пошук в усіх охоплюючих функціях в порядку зсередини назовні;
- пошук в поточній глобальній області видимості (пошук в поточному модулі);
- пошук у вбудованій області видимості (модуль buildins).
2. Якщо всередині функції оголошено глобальне ім’я з допомогою інструкції global, то пошук імені починається одразу з глобальної області видимості.
3. Якщо до деякого об’єкту використана операція присвоювання за замовчуванням (t = value), то ця операція:
- створює нове ім’я в локальній області видимості;
- змінює ім’я в поточній локальній області видимості.
4. Якщо всередині функції визначено глобальное ім’я (з допомогою ключового слова global), то операція присвоювання:
- створює нове ім’я в області видимості охоплюючого модуля;
- змінює ім’я, яке було оголошене в охоплюючому модулі.
5. Якщо всередині функції визначене нелокальне ім’я (інструкція nonlocal), то операція присвоювання:
- створює нове ім’я в найближчій охоплюючій функції;
- змінює ім’я, яке було створене в найближчій охоплюючій функції.
⇑
3. Приклади вкладених функцій
Приклад 1. Дано функцію SquareEquation(), яка обчислює розв’язки квадратного рівняння. Всередині функції міститься вкладена функція Disc(), яка обчислює дискримінант.
# Вкладені функції import math # Функція розв'язку квадратного рівняння, # дана функція є охоплюючою для вкладеної функції Disc(). # Функція повертає розв'язок рівняння у вигляді списку def SquareEquation(a, b, c): # Вкладена функція Disc() обчислення дискримінанту def Disc(a, b, c): d = b*b-4*a*c return d # Обчислити дискримінант D = Disc(a, b, c) if D>=0: x1 = (-b - math.sqrt(D))/(2*a) x2 = (-b + math.sqrt(D))/(2*a) return [x1, x2] else: return None # Викликати функцію для розв'язку рівняння 2*x^2+3*x-5=0 Res = SquareEquation(2, 3, -5) if Res!=None: print('Result = ', Res) else: print('The equation has no roots')
Результат роботи програми:
Result = [-2.5, 1.0]
Приклад 2.
У прикладі реалізована функція CalcComplex(), яка на основі заданого значення n реалізує вкладені функції обчислення:
- суми комплексних чисел – функція AddComplex();
- різниці комплексних чисел – функція SubComplex().
Функція CalcComplex() повертає результат у вигляді списку.
# Вкладені функції import math # Функція CalcComplex(), яка на основі заданого числа викликає # вкладену функцію обчислення відповідного виразу. def CalcComplex(n, a1, b1, a2, b2): if n==1: # Визначити функцію AddComplex() - додавання комплексних чисел def AddComplex(a1, b1, a2, b2): real = a1+a2 # дійсна частина комплексного числа imag = b1+b2 # уявна частина комплексного числа return [real, imag] # Викликати функцію AddComplex() result = AddComplex(a1, b1, a2, b2) # повернути результат return result if n==2: # Визначити функцію SubComplex() def SubComplex(a1, b1, a2, b2): real = a1-a2 # дійсна частина imag = b1-b2 # уявна частина return [real, imag] # Викликати функцію SubComplex() result = SubComplex(a1, b1, a2, b2) # Повернути результат return result # Інакше повернути None return None # Знайти суму комплексних чисел: # (2-3*j) + (-2+5*j) Result = CalcComplex(1, 2, -3, -2, 5) # Вивести результат print("Result = ", Result)
Результат роботи програми
Result = [0, 2]
⇑
4. Фабричні функції. Основні поняття. Приклад
Як відомо, при виклику функції створюється об’єкт цієї функції. Цей об’єкт має свою адресу (посилання). У випадку вкладених функцій можна зберегти об’єкт вкладеної функції в охоплюючій функції. Якщо збережено об’єкт вкладеної функції, то така функція називається фабричною функцією. При цьому до охоплюючої функції ставиться вимога: охоплююча функція повинна повернути посилання на об’єкт вкладеної функції в операторі return.
Після оголошення фабричної функції у програмі, її можна використовувати наступним чином:
- створювати об’єкт фабричної функції з допомогою виклику охоплюючої функції. При цьому створюється посилання на об’єкт фабричної функції. Крім того, в об’єкті фабричної функції запам’ятовуються усі значення, які були їй передані з охоплюючої функції;
- викликати фабричну функцію з допомогою створеного посилання.
У загальному випадку, процес створення та використання фабричної функції виглядає наступним чином.
1. Оголосити вкладені функції як показано нижче
def Fn1(parameters1): ... def Fn2(parameters2): # це є фабрична функція ... # використання параметрів parameters1 охоплюючої функції # ... ... return value # функція Fn2() повертає деякий результат ... return Fn2 # функція Fn1() повертає посилання на об’єкт функції Fn2()
2. Отримати посилання на об’єкт вкладеної фабричної функції. Щоб отримати посилання, потрібно звернутись до охоплюючої функції Fn1() з аргументами, які їй передаються
ref = Fn1(arguments1)
У цьому випадку аргументи arguments1 охоплюючої функції Fn1() конвертуються в параметри parameters1. Ці параметри використовуються і запам’ятовуються в об’єкті вкладеної функції Fn2().
3. Викликати об’єкт фабричної функції Fn2() за посиланням ref
ref(arguments2)
тут arguments2 конвертуються в parameters2 вкладеної функції Fn2.
Таким чином, у програмі виникає виклик фабричної функції
Fn1(arguments1)(arguments2)
Приклад 1. Функція, яка обчислює факторіал числа n: n! = 1·2·3· … ·n.
# Фабричні функції. Обчислення факторіалу числа # 1. Визначити зовнішню функцію Factorial(n), # яка просто оголошує і повертає вкладену функцію Fact() def Factorial(n): # Оголосити вкладену функцію обчислення факторіалу def Fact(): # функція Fact() запам'ятовує значення n # з охоплюючої області видимості і використовує його if (n<=0): return 0 i=1 res=1 while i<=n: res=res*i i=i+1 return res # Повернути результат функції Fact не викликаючи її return Fact # 2. Запам'ятати посилання на функцію Factorial(5), # яка обчислює 5! ref5 = Factorial(5) # Вивести посилання print("ref5 = ", ref5) # ref5 = <function Factorial.<locals>.Fact at 0x035176A8> # Викликати функцію обчислення факторіалу 5! за посиланням # та отримати результат F5 = ref5() print("5! = ", F5) # 5! = 120 # 3. Отримати інше посилання на функцію, яка обчислює 8! ref8 = Factorial(8) # Вивести посилання ref8 та результат обчислення 8! print('ref8 = ', ref8) print("8! = ", ref8()) # 4. Одразу звернутися до функції обчислення факторіалу 10! через посилання print("10! = ", Factorial(10)()) # 5. Знову викликати функцію обчислення 5! через посилання ref5, # посилання ref5 запам'ятовується print("5! = ", ref5()) # 5! = 120
Результат роботи програми
ref5 = <function Factorial.<locals>.Fact at 0x032E2150> 5! = 120 ref8 = <function Factorial.<locals>.Fact at 0x033376A8> 8! = 40320 10! = 3628800 5! = 120
Приклад 2. Використання фабричної функції, яка отримує параметри. У прикладі оголошуються функції, які обчислюють корінь n-го степеня з числа x. Охоплююча функція отримує значення n, яке запам’ятовується у фабричній функції, яка, в свою чергу, отримує параметр x.
# Вкладені функції. Фабричні функції # Взяття кореня n-го степеня з числа x # 1. Оголосити охоплюючу функцію Root() з вкладеною функцією Rt() def Root(n): # корінь n-го степеня # Оголосити вкладену функцію, яка отримує число x def Rt(x): # у вкладеній функції запам'ятовується параметр n охоплюючої функції return x**(1.0/n) # Повернути посилання на вкладену функцію return Rt # 2. Запам'ятати посилання на охоплюючу функцію з параметром 3 ref = Root(3) # ref = <function Root.<locals>.Rt at 0x0032B588> print('ref = ', ref) # 3. Обчислити корінь 3-го степеня з числа 27 result = ref(27) # викликаєтсья Root(3)(27) print('27^(1/3) = ', result)
Результат роботи програми
ref = <function Root.<locals>.Rt at 0x030E2150> 27^(1/3) = 3.0
⇑
5. Передача даних з охоплюючої області видимості у вкладену функцію з допомогою аргументів за замовчуванням. Приклад
З об’ємлючої функції можна передати дані у вкладену функцію з допомогою аргументів за замовчуванням. Загальна форма такої передачі наступна
def FnOut: varOut = value def FnIn(varIn = varOut): # varOut - аргумент за замовчуванням # використання varIn ... return ... return
тут
- FnOut – охоплююча функція;
- FnIn – вкладена функція;
- varOut – змінна в охоплюючій функції, яка передається у внутрішню функцію;
- value – значення, яке отримує змінна в varOut в охоплюючій функції;
- varIn – змінна у вкладеній функції, якій передається значення змінної varOut охоплюючої функції. Передача значення відбувається у вигляді рядка varIn=varOut.
Приклад.
У прикладі реалізується обчислення площі трикутника за формулою Герона. У вкладену функцію Semiperimeter передаються три аргументи за замовчуванням з функції AreaTriangle.
# Вкладені функції # Підключити математичний модуль import math # Визначити функцію AreaTriangle(), # яка обчислює площу трикутника за формулою Герона # на основі довжин його сторін a, b, c. def AreaTriangle(a, b, c): # Перевірка, чи з сторін a, b, c можна утворити трикутник if (((a+b)<c)or((b+c)<a)or((a+c)<b)): return 0 # У функції AreaTriangle() визначається # вкладена функція Semiperimeter(), яка отримує параметри a, b, c # охоплюючої функції і на основі цих параметрів обчислює півпериметер. # Параметри a, b, c отримуються як аргументи за замовчуванням def SemiPerimeter(a=a, b=b, c=c): return (a+b+c)/2 # Обчислити півпериметер p = SemiPerimeter(a, b, c) # Обчислити площу area = math.sqrt(p*(p-a)*(p-b)*(p-c)) return area # Продемонструвати роботу функції AreaTriangle() Area = AreaTriangle(5, 7, 3) print('Area = ', Area) Area = AreaTriangle(1, 1, 5) print('Area = ', Area)
Результат роботи програми
Area = 6.49519052838329 Area = 0
⇑
Зв’язані теми
- Поняття функції. Загальна форма. Приклади оголошення та використання функцій
- Області видимості імен в Python. Локальні та глобальні імена. Правила видимості імен. Правило LEGB. Ключове слово global. Перевизначення імен в функціях
⇑