Ключове слово nonlocal. Особливості використання. Приклади
Перед використанням даної теми рекомендується ознайомитись з наступною темою:
Зміст
- 1. Для чого призначена інструкція nonlocal? Загальна форма використання
- 2. Особливості застосування інструкції nonlocal. Відмінність між інструкціями global та nonlocal
- 3. Особливості застосування інструкції nonlocal у випадку, якщо використовується декілька рівнів вкладених функцій. Приклад
- 4. Вимоги до охоплюючих функцій, що містять вкладені функції з інструкціями nonlocal
- 5. Відмінності в правилах пошуку імен інтерпретатором в інструкціях global та nonlocal
- 6. Приклади використання інструкції nonlocal
- 7. Які обмеження накладаються на інструкцію nonlocal?
- 8. Приклад, в якому в інструкції nonlocal оголошується декілька імен
- Зв’язані теми
Пошук на інших ресурсах:
1. Для чого призначена інструкція nonlocal? Загальна форма використання
Інструкція nonlocal використовується у випадках, коли в програмі реалізовано вкладені функції. Інструкція nonlocal призначена для зміни значення змінної охоплюючої функції у тілі вкладеної функції. Таким чином, вкладена функція має доступ до змінних охоплюючих функцій.
Використання цього механізму дає можливість підтримувати доступну до зміни інформацію про стан, яка відновлюється при наступних викликах вкладеної функції.
Загальна форма використання інструкції nonlocal
def Fn(): nonlocal name1, name2, ..., nameN
тут
- Fn() – функція, яка є вкладеною в деякій іншій функції;
- name1, name2, nameN – імена, що існують в області видимості охоплюючої функції. Функція Fn() є вкладеною в іншу охоплюючу функцію.
У випадку простого вкладення функції FnIn() в межах охоплюючої функції FnOut() загальна форма оголошення інструкції nonlocal наступна:
def FnOut(): ... def FnIn(): nonlocal name1, name2, ..., nameN ...
тут
- FnOut() – охоплююча функція, в якій оголошується вкладена функція FnIn();
- FnIn() – вкладена функція, що містить інструкцію nonlocal;
- name1, name2, nameN – імена, які оголошені в охоплюючій функції FnOut() і використовуються у вкладеній функції FnIn().
⇑
2. Особливості застосування інструкції nonlocal. Відмінність між інструкціями global та nonlocal
Інструкція nonlocal застосовується у вкладених функціях коли потрібно змінювати змінні, що були оголошені в охоплюючих функціях.
Відмінність між інструкціями nonlocal та global наступна:
- інструкція global дозволяє змінювати значення змінних в глобальній області видимості модуля;
- інструкція nonlocal змінює значення змінних в охоплюючій функції. Для глобальної області видимості інструкція nonlocal не має дії.
⇑
3. Особливості застосування інструкції nonlocal у випадку, якщо використовується декілька рівнів вкладених функцій. Приклад
Приклад. Нехай задано декілька вкладених функцій. Зовнішня функція Fn1() містить вкладену функцію Fn2(). Вкладена функція Fn2() містить іншу вкладену функцію Fn3(). У функціях Fn1() та Fn2() оголошується змінна з іменем x1, якій присвоюється деяке значення. У функції Fn3() змінна x1 змінюється з допомогою інструкції nonlocal. У результаті буде змінюватись змінна x1 найближчої охоплюючої функції, у нашому випадку – функції Fn2().
# Інструкція nonlocal # Декілька охоплюючих функцій def Fn1(): # ця змінна не змінюється з функції Fn3(), # тому що її перекриває змінна з функції Fn2() x1 = 25 def Fn2(): x1 = 33 # ця змінна буде змінюватись у функції Fn3() def Fn3(): nonlocal x1 x1 = 55 # Fn2.x1 = 55 Fn3() print('Fn2.x1 = ', x1) Fn2() print('Fn1.x1 = ', x1) Fn1()
Результат виконання програми
Fn2.x1 = 55 Fn1.x1 = 25
Якщо у тілі функції Fn2() забрати рядок x1 = 33, то змінюватись буде значення змінної x1 функції вищого рівня, тобто функції Fn1(). У цьому випадку програма видасть результат
Fn2.x1 = 55 Fn1.x1 = 55
⇑
4. Вимоги до охоплюючих функцій, що містять вкладені функції з інструкціями nonlocal
Для того щоб у вкладеній функції використовувати інструкцію nonlocal потрібно, щоб виконувались наступні умови:
- програма містила код вкладених функцій. Одна з функцій вважається охоплюючою, інша – вкладеною;
- в охоплюючій функції була оголошена змінна, яка змінюється у вкладеній функції. Ця змінна повинна бути оголошена перед оголошення вкладеної функції.
⇑
5. Відмінності в правилах пошуку імен інтерпретатором в інструкціях global та nonlocal
Якщо у вкладеній функції використовується інструкція nonlocal, то інтерпретатор виконує наступні дії:
- пропускає локальну область видимості функції, в якій оголошена інструкція nonlocal;
- здійснює пошук в областях видимості охоплюючих функцій починаючи з найближчої охоплюючої функції.
У випадку використання інструкції global у вкладеній функції інтерпретатор здійснює пошук в області імен охоплюючого модуля (глобальній області видимості).
⇑
6. Приклади використання інструкції nonlocal
Приклад 1. У прикладі продемонстровано доступ до змінної out охоплюючої функції FnOut() з функції FnIn().
# Інструкція nonlocal # Охоплююча функція FnOut() def FnOut(): out = 25 # оголосити змінну out # Вкладена функція, в якій використовується інструкція nonlocal def FnIn(): # доступ до змінної out охоплюючої функції FnOut() nonlocal out out = 777; return # Виклик вкладеної функції FnIn() з тіла функції FnOut() FnIn() # Вивід змінної out print('FnOut.out = ', out) # Глобальна область видимості. # Виклик функції FnOut() FnOut() # буде виведено: FnOut.out = 777
Результат виконання програми
FnOut.out = 777
Як видно з результату, змінна out з функції FnOut() була змінена у тілі функції FnIn() завдяки інструкції nonlocal.
Приклад 2. Розв’язок квадратного рівняння. У прикладі демонструється доступ до змінних x1, x2 охоплюючої функції SquareEquition() з вкладеної функції Calc().
# Інструкція nonlocal. Розв'язок квадратного рівняння # Підключити математичний модуль для того, щоб # використати функцію math.sqrt() import math # Оголосити дві функції: охоплюючу SquareEquition() та вкладену Calc() def SquareEquition(a, b, c): # На початку прийняти, що рівняння не має коренів x1 = None x2 = None # Вкладена функція Calc() - заповнює значення x1, x2 def Calc(a, b, c): D = b*b-4*a*c if (D>=0): # доступ до x1, x2 охоплюючої функції SquareEquition() nonlocal x1, x2 # оголосити 2 імені в інструкції nonlocal x1 = (-b - math.sqrt(D))/(2.0*a) x2 = (-b + math.sqrt(D))/(2.0*a) Calc(a, b, c) return [x1, x2] # Використання функції SquareEquition(), # ввід даних print("Input a, b, c:") a = float(input('a = ')) b = float(input('b = ')) c = float(input('c = ')) roots = SquareEquition(a, b, c) print('roots = ', roots)
Результат роботи програми
Input a, b, c: a = 1 b = 1 c = -2 roots = [-2.0, 1.0]
⇑
7. Які обмеження накладаються на інструкцію nonlocal?
На інструкцію nonlocal накладаються наступні обмеження:
- ім’я, що оголошується в інструкції nonlocal на момент виклику у вкладеній функції, повинні вже існувати в охоплюючій функції;
- при використанні інструкції пошук імен здійснюється тільки в областях видимості охоплюючих функцій. У вбудованій та глобальній областях видимості пошук нелокальних імен не здійснюється, навіть якщо в цих областях такі імена вже існують (дивіться приклад нижче).
Приклад. Якщо спробувати виконати наступний приклад
# Обмеження, що накладаються на nonlocal D = 'Hello' # Оголосити глобальне ім'я def FnOut(): def FnIn(): # спроба зв'язати ім'я D з глобальним іменем D nonlocal D D = 'world!' # Викликати функцію FnIn() з тіла функції FnOut() FnIn() print('FnIn.D = ', D) # Викликати функцію FnOut() з області видимості модуля FnOut()
то інтерпретатор видасть помилку:
SyntaxError: no binding for nonlocal 'D' found
Це означає, що ім’я D повинно бути попередньо оголошене в охоплюючій функції FnOut(), а не в глобальній області видимості. Наприклад функція FnOut() може бути змінена наступним чином
... def FnOut(): D = 'Hello' def FnIn(): # ім'я D зв'язується з іменем D охоплюючої функції nonlocal D D = 'world!' # Викликати функцію FnIn() з тіла функції FnOut() FnIn() print('FnIn.D = ', D) ...
Після цього програма запрацює і видасть результат
FnIn.D = world!
⇑
8. Приклад, в якому в інструкції nonlocal оголошується декілька імен
# Додавання комплексних чисел (a1+b1*j)+(a1+b2*j) def ComplexAdd(a1, b1, a2, b2): a3 = 0 b3 = 0 def Add(): nonlocal a3, b3 # Використання двох імен в інструкції nonlocal a3 = a1+a2 b3 = b1+b2 Add() return [a3, b3] result = ComplexAdd(2, 3, -1, 4) print('result = ', result) # result = [1, 7]
⇑
Зв’язані теми
- Поняття функції. Загальна форма. Приклади оголошення та використання функцій
- Області видимості імен в Python. Локальні та глобальні імена. Правила видимості імен. Правило LEGB. Ключове слово global. Перевизначення імен в функціях
- Вкладені функції. Вкладені області видимості. Правила пошуку імен у випадку вкладених функцій. Фабричні функції. Передача значень у вкладену функцію
⇑