Python видимость переменных во вложенных функциях

Python. Вложенные функции. Вложенные области видимости. Правила поиска имен в случае вложенных функций. Фабричные функции. Передача значений во вложенную функцию

Вложенные функции. Вложенные области видимости. Правила поиска имен в случае вложенных функций. Фабричные функции. Передача значений во вложенную функцию

Поиск на других ресурсах:

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 , то поиск имени начинается сразу с глобальной области видимости.

Читайте также:  Java url add params

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')

Результат работы программы:

В примере реализована функция CalcComplex() , которая на основе заданного значения n реализует вложенные функции вычисления:

  • суммы комплексных чисел – функция AddComplex() ;
  • разности комплексных чисел – функция SubComplex() .

Функция CalcComplex() возвращает результат в виде списка.

  • создавать объект фабричной функции с помощью вызова объемлющей функции. При этом создается ссылка на объект фабричной функции. Кроме того, в объекте фабричной функции запоминаются все значения, которые были ей переданы из объемлющей функции;
  • вызвать фабричную функцию с помощью созданной ссылки.

2. Получить ссылку на объект вложенной фабричной функции. Чтобы получить ссылку, нужно обратиться в объемлющую функцию Fn1() с аргументами, которые ей передаются

В этом случае аргументы arguments1 объемлющей функции Fn1() конвертируются в параметры parameters1 . Эти параметры используются и запоминаются в объекте вложенной функции Fn2() .

3. Вызвать объект фабричной функции Fn2() с помощью ссылки ref

здесь arguments2 конвертируются в parameters2 вложенной функции Fn2 .

Таким образом, в программе возникает вызов фабричной функции

Пример 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 ireturn res # Вернуть результат функции Fact() не вызывая ее return Fact # 2. Запомнить ссылку на функцию Factorial(5), # которая вычисляет 5! ref5 = Factorial(5) # Вывести ссылку print("ref5 color: #ff0000;"># ref5 = .Fact at 0x035176A8> # Вызвать функцию вычисления факториала 5! по ссылке # и получить результат F5 = ref5() print("5! color: #ff0000;"># 5! = 120 # 3. Получить другую ссылку на функцию, которая вычисляет 8! ref8 = Factorial(8) # Вывести ссылку ref8 и результат вычисления 8! print('ref8 = ', ref8) print("8! color: #ff0000;"># 4. Сразу обратиться к функции вычисления факториала 10! по ссылке print("10! color: #ff0000;"># 5. Снова вызвать функцию вычисления 5! через ссылку ref5, # ссылка ref5 запоминается print("5! color: #ff0000;"># 5! = 120

Результат работы программы

ref5 = .Fact at 0x032E2150> 5! = 120 ref8 = .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 = .Rt at 0x0032B588> print('ref = ', ref) # 3. Вычислить корень 3-й степени из числа 27 result = ref(27) # вызывается Root(3)(27) print('27(1/3) = ', result)

Результат работы программы

ref = .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)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 видимость переменных во вложенных функциях

Область видимости или scope определяет контекст переменной, в рамках которого ее можно использовать. В Python есть два типа контекста: глобальный и локальный.

Глобальный контекст

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

name = "Tom" def say_hi(): print("Hello", name) def say_bye(): print("Good bye", name) say_hi() say_bye()

Здесь переменная name является глобальной и имеет глобальную область видимости. И обе определенные здесь функции могут свободно ее использовать.

Локальный контекст

В отличие от глобальных переменных локальная переменная определяется внутри функции и доступна только из этой функции, то есть имеет локальную область видимости:

def say_hi(): name = "Sam" surname = "Johnson" print("Hello", name, surname) def say_bye(): name = "Tom" print("Good bye", name) say_hi() say_bye()

В данном случае в каждой из двух функций определяется локальная переменная name. И хотя эти переменные называются одинаково, но тем не менее это две разных переменных, каждая из которых доступна только в рамках своей функции. Также в функции say_hi() определена переменная surname, которая также является локальной, поэтому в функции say_bye() мы ее использовать не сможем.

Скрытие переменных

Есть еще один вариант определения переменной, когда локальная переменная скрывают глобальную с тем же именем:

name = "Tom" def say_hi(): name = "Bob" # скрываем значение глобальной переменной print("Hello", name) def say_bye(): print("Good bye", name) say_hi() # Hello Bob say_bye() # Good bye Tom

Здесь определена глобальная переменная name. Однако в функции say_hi определена локальная переменная с тем же именем name. И если функция say_bye использует глобальную переменную, то функция say_hi использует локальную переменную, которая скрывает глобальную.

Если же мы хотим изменить в локальной функции глобальную переменную, а не определить локальную, то необходимо использовать ключевое слово global :

name = "Tom" def say_hi(): global name name = "Bob" # изменяем значение глобальной переменной print("Hello", name) def say_bye(): print("Good bye", name) say_hi() # Hello Bob say_bye() # Good bye Bob

nonlocal

Выражение nonlocal прикрепляет идентификатор к переменной из ближайщего окружающего контекста (за исключением глобального контекста). Обычно nonlocal применяется во вложенных функциях, когда надо прикрепить идентификатор за переменной или параметром окружающей внешней функции. Рассмотрим ситуацию, где это выражение может пригодиться:

def outer(): # внешняя функция n = 5 def inner(): # вложенная функция print(n) inner() # 5 print(n) outer() # 5

Здесь вложенная локальная функция inner() выводит на консоль значение переменной n , которая определена во внешней функции outer(). Затем в функции outer() вызывается внутренняя функция inner().

При вызове функции outer() здесь мы ожидаемо увидим на консоли два раза число 5. Однако в данном случае вложенная функция inner() просто получает значение. Теперь возьмем другую ситуацию, когда вложенная функция присваивает значение переменной:

def outer(): # внешняя функция n = 5 def inner(): # вложенная функция n = 25 print(n) inner() # 25 print(n) outer() # 5 # 25 - inner # 5 - outer

При присвоении значения во вложенной функции: n = 25 будет создаваться новая переменная n, которая скроет переменную n из окружающей внешней функции outer. В итоге мы получим при выводе два разных числа. Чтобы во вложенной функции указать, что идентификатор во вложенной функции будет представлять переменную из окружающей функции, применяется выражение nonlocal :

def outer(): # внешняя функция n = 5 def inner(): # вложенная функция nonlocal n # указываем, что n - это переменная из окружающей функции n = 25 print(n) inner() # 25 print(n) outer() # 25

Источник

Оцените статью