Функции могут быть вложенными
Язык программирования Python позволяет определять функции внутри других функций. Их часто называют вложенными функциями или внутренними функциями. Вот пример:
def parent(): print('=> parent') def child(): print('=> I child function') child() >>> parent() # => parent # => I child function
Каждый раз, когда вызывается функция parent() , она определяет новую внутреннюю функцию child() , затем вызывает ее.
Важно: внутренние функции не определены до тех пор, пока не будет вызвана родительская функция. Они локально ограничены родительской функцией parent() . Они существуют только внутри функции parent() как локальные переменные. Попробуйте вызвать child() и получитe ошибку:
>>> child() # Traceback (most recent call last): # File "", line 1, in # NameError: name 'one_child' is not defined
Что если нужно получить доступ к вложенной функции извне? Функции — это объекты, следовательно можно вернуть внутреннюю функцию из вызывающей (родительской) функции.
Например, вот функция, определяющая две внутренние функции. В зависимости от аргумента, переданного функции верхнего уровня, она выбирает и возвращает вызывающей стороне одну из внутренних функций:
def talk(n): def hello(name): return f'Привет name>.' def goodbye(name): return f'Пока name>.' if n > 0: return hello else: return goodbye
Обратите внимание, что функция talk() не вызывает ни одну из своих внутренних функций, talk() просто выбирает соответствующую функцию на основе аргумента n , а затем возвращает объект function :
>>> talk(0) # .goodbye at 0x7fb665af5598> >>> talk(1) # .hello at 0x7fb66b1f58c8>
Можно вызвать возвращаемую функцию, либо напрямую, либо сначала присвоив ей имя переменной:
>>> say = talk(1) >>> say('Мир') # 'Привет Мир.' >>> talk(0)('Мир') # 'Пока Мир.'
Это означает, что функции могут не только принимать поведение через аргументы, но и могут возвращать поведение!
- КРАТКИЙ ОБЗОР МАТЕРИАЛА.
- Функции это объекты
- Функции могут иметь атрибуты
- Функции могут храниться в структурах данных
- Функции могут быть вложенными
- Передача функции в качестве аргумента другой функции
- Область видимости переменных функции
- Операторы global и nonlocal
- Параметры (аргументы) функции
- Ключевые аргументы в определении функции Python
- Значение аргумента по умолчанию в функциях Python
- Варианты передачи аргументов в функцию Python
- Переменные аргументов *args и **kwargs в функции Python
- Распаковка аргументов для передачи в функцию Python
- Как оцениваются аргументы при вызове функции?
- Строгие правила передачи аргументов в функцию Python
- Инструкция return
- Анонимные функции (lambda-выражения)
- Строки документации в функциях Python
- Рекурсия
- Замыкания в функциях Python
- Перегрузка функций
3. Добавление новых функций
Чтобы добавить в программный код функцию, созданную пользователем, нужно знать следующее.
- Заголовок функции начинается с оператора \(def\).
- Имя функции должно быть уникально и не встречаться в основной программе в виде имени переменных.
- Заголовок функции заканчивается двоеточием.
- В разделе пишем набор инструкций, и он имеет отступ от написания \(def\).
- Функция \(return\) может вернуть результат, но это необязательно.
- Вызвать созданную функцию можно с любой строки программы.
Синтаксис функции.
\(def\) ():
\(return\)
Напишем функцию, которая будет находить сумму двух чисел.
Функция вызывается внутри основной программы, например, так.
Рис. \(1\). Фрагмент программного кода
Рис. \(2\). Результат работы программы
Внутрь одной функции можно вложить ещё одну, такая функция будет называться вложенной.
Как вызвать функцию в Python?
Как известно, функции — это блоки инструкций, предназначенные для выполнения определенных задач в программировании. Функции позволяют разбивать большие фрагменты кода на более мелкие отрезки или модули. Позже их можно вызывать отовсюду. Это позволяет повторно использовать определенные части программы и избегать повторений. Функции можно определять внутри классов, модулей, вложенных функций и так далее.
Основные особенности функций в Python:
- Используются чтобы избегать повторений в коде,
- Используются для разделения кода на мелкие модули
- Позволяют скрывать код и создавать ясность для понимания модулей,
- Позволяют повторно использовать код и сохранять память,
- Код из функции можно выполнить только по ее имени,
- Простой синтаксис: def имя_функции(параметры): .
Правила создания функций:
- Для объявления функции в Python используется ключевое слово def .
- Название функции должно начинаться с символа латинского алфавита в любом регистре или нижнего подчеркивания.
- В каждой функции есть двоеточие и отступ, после которого записывается сам код программы.
- Зарезервированные ключевые слова не могут использоваться в качестве названия функции.
- Функция может содержать несколько параметров или не иметь их совсем.
Создание функции в Python
Для создания нужно написать ключевое слово def . Синтаксис следующий:
def function_name(): # логика функции return result # возврат значения
Создадим и вызовем реальную функцию в 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 , то поиск имени начинается сразу с глобальной области видимости.
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() возвращает результат в виде списка.
- создавать объект фабричной функции с помощью вызова объемлющей функции. При этом создается ссылка на объект фабричной функции. Кроме того, в объекте фабричной функции запоминаются все значения, которые были ей переданы из объемлющей функции;
- вызвать фабричную функцию с помощью созданной ссылки.
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 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
Связанные темы
- Понятие функции. Общая форма. Примеры объявления и использования функций
- Области видимости имен. Локальные имена. Правила видимости имен. Правило LEGB. Ключевое слово global . Переопределение имен в функциях
