Как сделать функцию в функции

Добавил пользователь Владимир З.
Обновлено: 04.10.2024

В предыдущих разделах мы уже часто сталкивались с встроенными функция ( int, float, print, type, len ) Каждая функция в Python предназначена для выполнения одной конкретной задачи. Использование функции упрощает написание и чтение кода.

1. Функция в Python

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

Напишем функцию, которая вычисляет квадрат своего аргумента и выводит на экран:

>>> def square ( number ):
. """Вычисление квадрата числа"""
. print(number ** 2)
.
>>> square (5)
25
>>> square (124.45)
15487.802500000002

Определение функции начинается с ключевого слова def , за которым следует имя функции - square . Имя функции, как и имена переменных рекомендуется писать с букв нижнего регистра, а в именах, состоящих из нескольких слов, составляющие должны разделяться символами подчеркивания. Далее в круглых скобках записываются параметры (аргументы) функции, разделенные запятыми. Функция square имеет только один аргумент с именем number - значение, возводимое в квадрат. В случае отсутствия параметров у функции пустые круглые скобки обязательны. В конце строки за параметрами всегда ставится двоеточие ( : ).

После двоеточия новая строка должна идти с отступом (4 пробела). Все строки с отступом образуют тело или блок функции. В "Руководстве по стилю кода Python" указано, что первой строкой блока функции должна быть doc-строка, кратко поясняющая назначение функции: """Вычисление квадрата числа""" . Сам код в теле функции состоит всего из одной строки print(number ** 2).

Команда squre(5) вызывает функции square() и передает ей значение аргумента, для выполнения команды print. Функция возводит число в квадрат и выводит на экран.

2. Передача аргументов функции в Python

2.1. Позиционные аргументы

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

>>> def car (car_brend, car_model, mileage):
. """Выводит информацию о автомобиле"""
. print(f"Продается с пробегом км.")
.
>>> car ('bmw', 'x5', 51345)
Продается Bmw X5 с пробегом 51345 км.

В данной функции видно, что должно передаваться три аргумента название автомобиля ( car_brend), модель (car_model) и пробег (mileage) . При вызове функции мы должны передать аргументы именно в том порядке, в каком они сохраняются в функции. Если нарушить порядок следования аргументов, то при вызове возможны неожиданные результаты или ошибки.

2.2. Именованные аргументы

Если порядок передачи аргументов по каким то причинам не известен, то можно использовать именованные аргументы. Именованный аргумент представляет собой пару "имя-значение". Имя и значения связываются с аргументом напрямую, так что при передаче аргумента путаница исключается. Вызовем туже самую функцию car() с помощью именованных аргументов:

>>> def car (car_brend, car_model, mileage):
. """Выводит информацию о автомобиле"""
. print(f"Продается с пробегом км.")
.
>>> car (mileage = 45152, car_model = 'x5', car_brend='bmw')
Продается Bmw X5 с пробегом 45152 км.

При обработке вызова функции Python знает к какому аргументу принадлежат данные и проблем с выводом не случается.

2.3. Значения по умолчанию

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

>>> def car (car_model, mileage, car_brend='bmv'):
. """Выводит информацию о автомобиле"""
. print(f"Продается с пробегом км.")
.
>>> car ('x7', 12345)
Продается Bmv X7 с пробегом 12345 км.

>>> car ('m5' , 56148)
Продается Bmv M5 с пробегом 56148 км.

Для изменения значения по умолчанию, мы можем передать именованный аргумент для изменения значения car_brend='audi':

>>> car ('q7', 35600, car_brend='audi')
Продается Audi Q7 с пробегом 35600 км.

Так как аргумент для параметра car_brend задан явно, Python игнорирует значение по умолчанию.

2.4. Передача произвольного набора аргументов

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

>>> def cars ( * args ):
. """Вывод автомобилей"""
. print( args )
.
>>> cars ('audi', 'bmv', 'ford', 'kia')
('audi', 'bmv', 'ford', 'kia')
>>> cars ('porshe')
('porshe')

Звездочка в имени параметра args приказывает создать Python пустой кортеж с именем args и упаковать в него все полученные результаты и с помощью команды print вывести на экран. В примере видно, что функция работает и при передаче четырех и при передаче одного аргумента.

Для более удобной работы с данными, например изменения регистра символов можно воспользоваться циклом for:

>>> def cars ( * args):
. """Вывод автомобилей в продаже"""
. print('Автомобили в продаже:')
. for arg in args:
. print(f"-")
.
>>> cars ('audi', 'bmv', 'ford', 'kia')
Автомобили в продаже:
-Audi
-Bmv
-Ford
-Kia

2.5. Позиционные аргументы с произвольным набором аргументов

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

>>> def car (car_brend, car_model, * colors):
. """Выводит информацию о автомобиле"""
. print(f"Автомобиль можно заказать в цветах:")
. for color in colors:
. print(f"-")
.
>>> car ('bmw', 'x7', 'синий', 'зеленый', 'белый', 'черный', 'желтый')
Автомобиль Bmw X7 можно заказать в цветах:
-синий
-зеленый
-белый
-черный
-желтый

В результате данная функция получает два позиционных аргумента car_brend и car_model, а остальные сохраняются в кортеже colors.

В большинстве программ часто используется имя обобщенного параметра *args для хранения произвольного набора позиционных аргументов.

2.6. Произвольный набор именованных аргументов

Иногда может потребоваться, чтобы функция получала произвольное количество именованных аргументов. В таком случае можно написать функцию, которая получает столько пар "ключ-значение", сколько указано в команде вызова. Например, для построение пользовательских профилей, заранее не известно, какую точно информацию предоставит пользователь. Поэтому определим в функции обязательное предоставление имени и фамилии, а остальная информация может быть получена с помощью произвольного количества именованных аргументов:

>>> def profile (first, last, **user_info):
. """Возвращает словарь с данными о пользователе"""
. user_info['first_name'] = first
. user_info['last_name'] = last
. return user_info
.
>>> profile_1 = profile ('tomas', 'edisson', location='usa')
>>> print(profile_1)

Функция profile ожидает получить имя и фамилию пользователя, а также позволяет передать любое количество пар "имя - значение". Две звездочки в параметре **user_info заставляют Python создать пустой словарь с именем user_info и добавить в него все полученные пары "имя - значение". В теле функции сразу добавляются имя и фамилия, а остальные пары в зависимости от переданных параметров при вызове фукции. В конце словарь возвращается с помощью команды return .

В программах часто используется имя обобщенного параметра **kwargs для хранения произвольного набора ключевых аргументов.

3. Возвращаемое значение в функции на Python

Вместо вывода результата работы напрямую, функция может обработать данные и вернуть значение c помощью команды return . Значение, возвращаемое функцией, называется возвращаемым значением.

3.1. Возвращение простого значения

Напишем функцию, которая возвращает отформатированное имя и фамилию

>>> def form_name (last_name, first_name, middle_name):
. """Возвращает отформатированное полное имя"""
. full_name = f" "
. return full_name.title()
.
>>> poet = form_name ('пушкин', 'александр', 'сергеевич')
>>> print(poet)
Пушкин Александр Сергеевич

Функция form_name получает в параметрах имя, фамилию и отечество, далее объединяет эти имена и сохраняет их в переменной full_name. Завершив выполнение, функция возвращает управление в точку вызова с помощью команды return , то есть в строку кода, которая вызывала функцию.

Предположим, что мы не знаем отчество человека, для передачи его фукции параметру middle_name. В связи с этим удобно заранее сделать в функции необязательный аргумент . Присвоим ( middle_name = "" ) пустое значение.

>>> def form_name (last_name, first_name, middle_name=''):
. """Возвращает отформатированное полное имя"""
. full_name = f" "
. return full_name.title()
.
>>> poet = form_name ('пушкин', 'александр')
>>> print(poet)
Пушкин Александр
>>> poet = form_name('пушкин', 'александр', 'сергеевич')
>>> print(poet)
Пушкин Александр Сергеевич

С необязательным аргументом мы не получим ошибку (TypeError: form_name() missing 1 required positional argument: 'middle_name') в случае отсутствия на входе данных по аргументу.

3.2. Возвращение словаря

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

>>> def info_person (first_name, last_name):
. """Возвращает словарь с данными о человеке"""
. person =
. return person
.
>>> musician = info_person ('Freddie', 'Mercury')
>>> print(musician)

При вызове функции info_person получает имя и фамилию на входе и помещает их сразу в словарь, с ключами имя и фамилия. Затем с помощью команды return возвращает словарь. В будущем со словарем будет удобнее работать, мы сможем отдельно использовать имя, фамилию или другие аргументы функции.

4. Использования функции в цикле while

Функции могут вызываться в циклах while где угодно. Приведем пример цикла while, где у посетителя запрашивают имя и фамилию, а с помощью функции form_name возвращается отформатированное имя и фамилия с приветствием:

def form_name (first_name, last_name):
"""Возвращает отформатированное полное имя"""
full_name = f" "
return full_name.title()

while True:
print("\nВведите 'x' если хотите завершить программу")
first_name = input("Введите ваше имя: ")
if first_name == 'x':
break
last_name = input("Введите вашу фамилию: ")
if last_name == 'x':
break
formatted_name = form_name (first_name, last_name)
print(f"\nДобрый день !")

В данном примере в цикле whle запрашивается имя и фамилия и с помощью функции form_name возвращается отформатированное полное имя и записывается в переменную formatted_name. А затем уже с помощью функции print данные выводятся на экран.

5. Передача списка функции на Python

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

>>> def square (numbers):
. """Вычисление квадрата числа"""
. for number in numbers:
. print(number ** 2)
.
>>> numbers = [1, 5, 6, 15, -7, 1.5]
>>> square (numbers)
1
25
36
225
49
2.25

В результате функции square мы передаем список numbers. Для возведения всех чисел в квадрат, вначале нам нужно перебрать данный список с помощью цикла for, а затем каждое число возвести в квадрат.

6. Использование лямбда-выражений вместо функций

Для простых функций, например square, который просто вычисляют квадрат числа, можно использовать лямбда-выражения.

>>> square = lambda x : x ** 2
>>> print(square(5))
25

В начале создается переменная square и в дальнейшем по имени переменной будет вызываться лямбда-выражение. Лямбда-выражение является анонимной функцией, то есть функцией, не имеющей имени. Лямбда-выражение начинается с ключевого слова lambda , за которым следует разделенный запятыми список параметров. В нашем примере параметр один x. Затем ставится двоеточие и само выражение x ** 2. В результате при вызове переменной square мы передаем параметр число 5, и оно возводится в квадрат.

Лямбда-выражение может иметь и несколько параметров. Например, перемножать передаваемые числа.

>>> mult = lambda x, y, z : x * y * z
>>> print(mult(2, 4, 6))
48

Таким образом любая простая функция в форме

может быть выражена в более компактной форме посредством лямбда-выражения

Python позволяет разделить большую программу на основные строительные блоки, известные как функции.

Что такое функция в Python?

Функции в Python – это организованный блок многократно используемого кода, который можно вызывать при необходимости.

Функция содержит набор программных операторов, заключенных в <>. Функцию можно вызывать несколько раз, чтобы обеспечить возможность повторного использования и модульность программы Python.

Функция помогает программисту разбить программу на более мелкие части. Она очень эффективно организует код и избегает повторения кода. По мере роста программы функция делает ее более организованной.

Python предоставляет нам различные встроенные функции, такие как range() или print(). Пользователь также может создавать свои функции, которые можно назвать пользовательскими функциями.

В основном есть два типа функций:

  • Функции, определяемые пользователем. Определяются пользователем для выполнения конкретной задачи.
  • Встроенные функции. Это те функции, которые предварительно определены в Python.

В этом руководстве мы обсудим функции, определяемые пользователем.

Преимущество функций в Python

У функций Python есть следующие преимущества:

  • Используя функции, мы можем избежать повторной перезаписи одной и той же логики / кода снова и снова в программе.
  • Мы можем вызывать функции Python несколько раз и в любом месте программы.
  • Мы можем легко отслеживать большую программу Python, если она разделена на несколько функций.
  • Возможность повторного использования – главное достижение.
  • Однако вызов функции всегда является накладным.

Создание

Python предоставляет ключевое слово def для определения функции. Синтаксис функции определения приведен ниже.

Давайте разберемся с синтаксисом определения функций.

  • Ключевое слово def вместе с именем функции используется для определения функции.
  • Правило идентификатора должно следовать за именем функции.
  • Функция принимает параметр(аргумент), и они могут быть необязательными.
  • Функциональный блок начинается с двоеточия(:), и операторы блока должны иметь такой же отступ. используется для возврата значения. Функция может иметь только один возврат.

Вызов функции

В Python после создания функции мы можем вызывать ее из другой функции. Перед вызовом функция должна быть определена; в противном случае интерпретатор Python выдает ошибку. Чтобы вызвать функцию, используйте имя функции, за которым следуют круглые скобки.

Выход:
hello world

Оператор возврата return

Оператор return используется в конце функции и возвращает результат функции. Он завершает выполнение функции и передает результат туда, где функция вызывается. Оператор return не может использоваться вне функции.

Он может содержать выражение, которое оценивается, и значение возвращается вызывающей функции. Если оператор return не имеет выражения или не существует сам по себе в функции, он возвращает объект None.

Рассмотрим следующие примеры:

Выход:
The sum is: 30

В приведенном выше коде мы определили функцию с именем sum, и у нее есть оператор c = a + b, который вычисляет заданные значения, а результат возвращается оператором return вызывающей функции.

Пример 2. Создание функции без оператора возврата

В приведенном выше коде мы определили ту же функцию без оператора return, так как мы видим, что функция sum() вернула объект None вызывающей функции.

Аргументы в функции

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

Рассмотрим следующие примеры, содержащий функцию, которая принимает строку в качестве аргумента.

Вызов по ссылке в Python

В Python вызов по ссылке означает передачу фактического значения в качестве аргумента функции. Все функции вызываются по ссылке, т. е. все изменения, внесенные в ссылку внутри функции, возвращаются к исходному значению, на которое ссылается ссылка.

Пример 1. Передача неизменяемого объекта(списка)

Выход:
печать строки внутри функции: Hi I am there Hows you
печать строки вне функции: Hi I am there.

Типы аргументов

Может быть несколько типов аргументов, которые могут быть переданы во время вызова функции.

  1. Обязательные аргументы.
  2. Аргументы ключевого слова.
  3. По умолчанию.
  4. Переменной длины.

Обязательные

Мы можем предоставить аргументы во время вызова функции. Обязательные аргументы – это аргументы, которые необходимо передать во время вызова функции с точным совпадением их позиций в вызове функции и определении функции. Если какой-либо из аргументов не указан в вызове функции или положение аргументов изменено, интерпретатор Python покажет ошибку.

Рассмотрим следующие примеры.

Выход:
Введите имя: Джон
привет, Джон

Пример 2.

Выход:
Введите основную сумму: 5000
Введите процентную ставку: 5
Введите время в годах: 3
Простой процент: 750,0

Пример 3

Выход:
TypeError: calculate() отсутствует 1 обязательный позиционный аргумент: 'b'

Аргументы по умолчанию

Python позволяет нам инициализировать аргументы при определении функции. Если значение любого из аргументов не предоставляется во время вызова функции, то этот аргумент может быть инициализирован значением, указанным в определении, даже если аргумент не указан при вызове функции.

Выход:
My name is John and age is 22
Пример 2.

Выход:
My name is john and age is 22
My name is David and age is 10

Аргументы переменной длины(* args)

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

Однако при определении функции мы определяем аргумент переменной длины, используя * args(звездочку) как * .

Рассмотрим следующий пример:

Выход:
type of passed argument is
printing the passed arguments.
john
David
smith
nick

В приведенном выше коде мы передали * имена в качестве аргумента переменной длины. Мы вызвали функцию и передали значения, которые внутри обрабатываются как кортежи. Кортеж – это итеративная последовательность, такая же, как и список. Чтобы напечатать заданные значения, мы повторили имена * arg, используя цикл for в Python.

Аргументы ключевого слова(** kwargs)

Python позволяет нам вызывать функцию с аргументами ключевых слов. Такой вызов функции позволит нам передавать аргументы в случайном порядке.

Имя аргументов рассматривается как ключевое слово и сопоставляется при вызове и определении функции. Если такое же совпадение найдено, значения аргументов копируются в определение функции.

Рассмотрим следующие примеры.

Выход:
printing the message with John and hello

Пример 2. С указанием значений в другом порядке при вызове.

Выход:
Simple Interest: 1900.0
Если мы предоставим другое имя аргументов во время вызова функции, будет выдана ошибка.

Рассмотрим следующий пример.

Выход:
TypeError: simple_interest() got an unexpected keyword argument 'time'

Python позволяет нам предоставлять сочетание необходимых аргументов и аргументов ключевого слова во время вызова функции. Однако обязательный аргумент не должен указываться после аргумента ключевого слова, т. е. после того, как аргумент ключевого слова встречается в вызове функции, следующие аргументы также должны быть аргументами ключевого слова.

Рассмотрим следующие примеры.

Выход:
printing the message with John , hello ,and David

Следующий пример вызовет ошибку из-за неправильного сочетания ключевого слова и требуемых аргументов, переданных в вызове функции.

Выход:
SyntaxError: positional argument follows keyword argument

Python предоставляет возможность передавать несколько аргументов ключевого слова, которые могут быть представлены как ** kwargs. Похож на * args, но сохраняет аргумент в формате словаря. Этот тип аргументов полезен, когда мы не знаем заранее количество аргументов.

Рассмотрим следующий пример:

Пример 6. Многие аргументы используют аргумент ключевого слова.

Объем переменных

Объем переменных зависит от места, где переменная объявляется. Переменная, объявленная в одной части программы, может быть недоступна для других частей.

В Python переменные определяются с двумя типами областей видимости:

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

Рассмотрим следующий пример.

Пример 1. Локальная переменная

Выход:
hello !! I am going to print a message.
File "/root/PycharmProjects/PythonTest/Test1.py", line 5, in
print(message)
NameError: name 'message' is not defined

Пример 2. Глобальная переменная

Функции являются одним из “первоклассных граждан” Python, что означает, что функции находятся на том же уровне, что и другие объекты Python, такие как целые числа, строки, модули и т. Д. Их можно создавать и уничтожать динамически, передавать другим функциям, возвращать в виде значений и т. Д.

Python поддерживает концепцию “вложенной функции” или “внутренней функции”, которая является просто функцией, определенной внутри другой функции. В остальной части статьи мы будем использовать слова “внутренняя функция” и “вложенная функция” взаимозаменяемо.

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

Определение внутренней функции

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

В приведенном выше примере функция 2() была определена внутри функции 1() , что делает ее внутренней функцией. Чтобы вызвать функцию 2() , мы должны сначала вызвать функцию 1() . Затем функция 1() вызовет функцию 2() в том виде, в каком она была определена внутри нее.

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

Код ничего не вернет при выполнении!

Вот еще один пример:

Код возвращает умножение двух чисел, то есть 10 и 5. Пример показывает, что внутренняя функция может обращаться к переменным, доступным во внешней функции.

До сих пор вы видели, что мы можем получить доступ к переменным внешней функции внутри внутренней функции. Что, если мы попытаемся изменить переменные внешней функции изнутри внутренней функции? Посмотрим, что получится:

Вывод показывает, что мы можем вывести значение переменной, определенной во внешней функции, из внутренней функции, но не изменять его. Оператор x помог нам создать новую переменную x внутри внутренней функции function 2() вместо изменения значения переменной x , определенной во внешней функции function1() .

В следующем разделе мы обсудим основные причины, по которым мы используем внутренние функции в Python.

Зачем использовать Внутренние Функции?

Инкапсуляция

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

В приведенном выше коде мы пытаемся вызвать функцию inner_increment () , но вместо этого получаем ошибку.

Теперь закомментируйте вызов inner_increment() и раскомментируйте вызов outer_function () , как показано ниже:

Приведенный выше сценарий показывает, что внутренняя функция, то есть inner_increment() защищена от того, что происходит снаружи, так как переменная x внутри функции inner_increment не зависит от значения, передаваемого параметру x внешней функции. Другими словами, переменные внутри внутренней функции недоступны вне ее. В таком дизайне есть большое преимущество. После проверки всех аргументов во внешней функции мы можем спокойно пропустить проверку ошибок во внутренней функции.

Закрытие и заводские функции

Все примеры, которые мы видели до сих пор, просто содержат обычные функции, которые были вложены в другие функции. Мы можем писать такие функции по-другому, вместо того чтобы вкладывать их в другие функции. У нас нет конкретной причины, почему мы должны их гнездить.

Однако для случая closures необходимо использовать вложенные функции.

Мы можем связывать/передавать данные в функцию, не обязательно передавая данные в функцию через параметры. Это делается с помощью закрытия. Это объект функции, который способен запоминать значения в охватывающих областях, даже если они недоступны в памяти. Это означает, что у нас есть замыкание, когда вложенная функция ссылается на значение, которое находится в ее охватывающей области.

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

Ниже приведены условия, которые необходимо выполнить для создания замыкания в Python:

  • Должна быть вложенная функция
  • Внутренняя функция должна ссылаться на значение, определенное в заключающей области
  • Заключающая функция должна возвращать вложенную функцию

Рассмотрим следующий пример:

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

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

В приведенном выше скрипте из функции power_n(power) мы создали два других объекта: power_two и power_three . Это делает power_n(power) фабричной функцией, поскольку она генерирует функции power_two и power_three для нас, используя параметр, который мы ей передаем.

Вывод

Внутренняя функция-это просто функция, определенная внутри другой функции. Внутренняя функция может получить доступ к переменным, которые были определены в области действия внешней функции, но она не может их изменить. Существует целый ряд причин, по которым нам может понадобиться создать внутреннюю функцию. Например, внутренняя функция защищена от того, что происходит снаружи. Внутренние функции также являются хорошим способом создания замыканий в Python.

Передача функции как аргумента. Структуры данных, содержащих перечень функций. Возврат функции из другой функции оператором return . Примеры

Содержание

  • 1. Передача функции в качестве аргумента. Общие понятия
  • 2. Примеры передачи функции в качестве аргумента
    • 2.1. Решение квадратного уравнения. Передача функции, вычисляющей дискриминант в качестве аргумента
    • 2.2. Пример передачи в функцию ссылки на функцию. Выполнение базовых операций над комплексными числами
    • 2.3. Пример конвертирования чисел из десятичной системы счисления в двоичную и шестнадцатеричную. Передача функций конвертирования в качестве параметров.
    • 2.4. Пример передачи в функцию двух ссылок на функции, которые оперируют числами

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

    1. Передача функции в качестве аргумента. Общие понятия

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

    • FuncArg — функция, ссылка на которую передается в другую функцию. Имя функции ( FuncArg ) есть ссылкой на функцию;
    • Func — имя функции, которая получает входным параметром ссылку на функцию FuncArg ;
    • parameters1 , parameters2 — соответственно параметры функций FuncArg() и Func() .
    2. Примеры передачи функции в качестве аргумента
    2.1. Решение квадратного уравнения. Передача функции, вычисляющей дискриминант в качестве аргумента

    В примере реализована функция SquareRoot() , которая возвращает корни квадратного уравнения. Функция получает 4 параметра:

    • func — имя ссылки на функцию;
    • a , b , c — коэффициенты квадратного уравнения.

    В теле функции SquareRoot() осуществляется вызов функции-параметра func() . При вызове указываются 3 параметра a , b , c .
    Чтобы не было ошибки, при вызове функции SquareRoot() из другого кода, нужно, чтобы имя ссылки соответствовало (ассоциировалось) функции, получающей строго 3 параметра. В противном случае, будет сгенерирована ошибка.

    Результат выполнения программы

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

    В примере реализовано 5 функций:

    • AddComplex() — возвращает сумму двух комплексных чисел в виде кортежа;
    • SubComplex() — возвращает разницу двух комплексных чисел в виде кортежа;
    • MulComplex() — возвращает произведение двух комплексных чисел;
    • DivComplex() — возвращает результат деления двух комплексных чисел. В случае деления на 0 функция возвращает пустой кортеж;
    • OperationComplex() — выполняет одну из четырех операций по ссылкам на соответствующие методы.

    Результат выполнения программы

    2.4. Пример передачи в функцию двух ссылок на функции, которые оперируют числами

    В примере демонстрируется передача двух ссылок на функции в качестве параметров. Заданы две функции:

    • SumNumbers() — определяет сумму цифр числа, которое задается входным параметром;
    • MaxDigit() — определяет максимальную цифру числа, которое есть входным параметром.

    С помощью функции OperationNumber() осуществляется вызов функций SumNumbers() и MaxDigit() . Функции SumNumbers() и MaxDigit() передаются в функцию OperationNumber() в качестве параметров.

    3. Структуры данных, содержащие перечень функций

    Поскольку функции являются объектами, то существует возможность создавать различные структуры данных, содержащих функции. При создании таких структур данных, каждую функцию и перечень ее параметров формируют в виде кортежа.

    Например, список функций с одним параметром может быть таким

    • func1 , func2 , …, funcN – перечень имен функций или ссылок на функции;
    • param1 , param2 , …, paramN – перечень параметров соответственно функций func1 , func2 , …, funcN .

    После такого описания можно вызвать функцию как элемент списка по образцу

    • имя LF[0][0] будет заменено именем func1 ;
    • имя LF[0][1] будет заменено именем param1 .
    4. Пример списка функций. Массив вызовов функции Convert_2_to_10() , которая конвертирует число из двоичной системы исчисления в десятичную

    В примере формируется список ListConvert , содержащий кортежи, состоящие из имени функции Convert_2_to_10() и параметра-строки. Функция Convert_2_to_10() конвертирует число из двоичной системы исчисления в десятичную систему исчисления. Функция получает входным параметром число в виде строки и возвращает преобразованное число также в виде строки.

    После такого объявления, использование функции FuncOut() может быть, например, таким

    Пример. В примере в функции ProcessList() реализована функция AvgList() , которая возвращает среднее арифметическое элементов списка, который есть входным параметром функции ProcessList() . Результатом работы функции ProcessList() является функция AvgList() .

    Для определения функции нужно всего лишь написать ключевое слово def перед ее именем, а после — поставить двоеточие. Следом идет блок инструкций.

    Последняя строка в блоке инструкций может начинаться с return , если нужно вернуть какое-то значение. Если инструкции return нет, тогда по умолчанию функция будет возвращать объект None . Как в этом примере:

    Функция инкрементирует глобальную переменную i и возвращает None (по умолчанию).

    Вызовы

    Для вызова функции, которая возвращает переменную, нужно ввести:

    Для вызова функции, которая ничего не возвращает:

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

    Функции могут быть вложенными:

    Функции — это объекты, поэтому их можно присваивать переменным.

    Инструкция return

    Возврат простого значения

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

    Возврат нескольких значений

    Пока что функция возвращала только одно значение или не возвращала ничего (объект None). А как насчет нескольких значений? Этого можно добиться с помощью массива. Технически, это все еще один объект. Например:

    Аргументы и параметры

    В функции можно использовать неограниченное количество параметров, но число аргументов должно точно соответствовать параметрам. Эти параметры представляют собой позиционные аргументы. Также Python предоставляет возможность определять значения по умолчанию, которые можно задавать с помощью аргументов-ключевых слов.

    Параметр — это имя в списке параметров в первой строке определения функции. Он получает свое значение при вызове. Аргумент — это реальное значение или ссылка на него, переданное функции при вызове. В этой функции:

    x и y — это параметры, а в этой:

    При определении функции параметры со значениями по умолчанию нужно указывать до позиционных аргументов:

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

    Выходит, что в следующем примере допущена ошибка:

    Для вызовов это работает похожим образом. Сначала нужно указывать все позиционные аргументы, а только потом необязательные:

    На самом деле, следующий вызов корректен (можно конкретно указывать имя позиционного аргумента), но этот способ не пользуется популярностью:

    А этот вызов некорректен:

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

    Можно не указывать ключевые слова, но тогда порядок имеет значение. Он должен соответствовать порядку параметров в определении:

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

    Второй аргумент можно пропустить:

    Чтобы обойти эту проблему, можно использовать словарь:

    Значение по умолчанию оценивается и сохраняется только один раз при определении функции (не при вызове). Следовательно, если значение по умолчанию — это изменяемый объект, например, список или словарь, он будет меняться каждый раз при вызове функции. Чтобы избежать такого поведения, инициализацию нужно проводить внутри функции или использовать неизменяемый объект:

    Еще один пример изменяемого объекта, значение которого поменялось при вызове:

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

    Указание произвольного количества аргументов

    Позиционные аргументы

    Иногда количество позиционных аргументов может быть переменным. Примерами таких функций могут быть max() и min() . Синтаксис для определения таких функций следующий:

    При вызове функции нужно вводить команду следующим образом:

    Python обрабатывает позиционные аргументы следующим образом: подставляет обычные позиционные аргументы слева направо, а затем помещает остальные позиционные аргументы в кортеж (*args), который можно использовать в функции.

    Если лишние аргументы не указаны, значением по умолчанию будет пустой кортеж.

    Произвольное количество аргументов-ключевых слов

    Как и в случае с позиционными аргументами можно определять произвольное количество аргументов-ключевых слов следующим образом (в сочетании с произвольным числом необязательных аргументов из прошлого раздела):

    При вызове функции нужно писать так:

    Python обрабатывает аргументы-ключевые слова следующим образом: подставляет обычные позиционные аргументы слева направо, а затем помещает другие позиционные аргументы в кортеж (*args), который можно использовать в функции (см. предыдущий раздел). В конце концов, он добавляет все лишние аргументы в словарь (**kwargs), который сможет использовать функция.

    Важно, что пользователь также может использовать словарь, но перед ним нужно ставить две звездочки (**):

    Порядок вывода также не определен, потому что словарь не отсортирован.

    Документирование функции

    Если изучить ее, обнаружатся два скрытых метода (которые начинаются с двух знаков нижнего подчеркивания), среди которых есть __doc__ . Он нужен для настройки документации функции. Документация в Python называется docstring и может быть объединена с функцией следующим образом:

    Команда docstring должна быть первой инструкцией после объявления функции. Ее потом можно будет извлекать или дополнять:

    Методы, функции и атрибуты, связанные с объектами функции

    Если поискать доступные для функции атрибуты, то в списке окажутся следующие методы (в Python все является объектом — даже функция):

    И несколько скрытых методов, функций и атрибутов. Например, можно получить имя функции или модуля, в котором она определена:

    Есть и другие. Вот те, которые не обсуждались:

    Рекурсивные функции

    Рекурсия — это не особенность Python. Это общепринятая и часто используемая техника в Computer Science, когда функция вызывает сама себя. Самый известный пример — вычисление факториала n! = n * n — 1 * n -2 * … 2 *1. Зная, что 0! = 1, факториал можно записать следующим образом:

    Другой распространенный пример — определение последовательности Фибоначчи:

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

    Важно!
    Рекурсия позволяет писать простые и элегантные функции, но это не гарантирует эффективность и высокую скорость исполнения.

    Если рекурсия содержит баги (например, длится бесконечно), функции может не хватить памяти. Задать максимальное значение рекурсий можно с помощью модуля sys .

    Глобальная переменная

    Вот уже знакомый пример с глобальной переменной:

    Здесь функция увеличивает на 1 значение глобальной переменной i . Это способ изменять глобальную переменную, определенную вне функции. Без него функция не будет знать, что такое переменная i . Ключевое слово global можно вводить в любом месте, но переменную разрешается использовать только после ее объявления.

    За редкими исключениями глобальные переменные лучше вообще не использовать.

    Присвоение функции переменной

    С существующей функцией func синтаксис максимально простой:

    Переменным также можно присваивать встроенные функции. Таким образом позже есть возможность вызывать функцию другим именем. Такой подход называется непрямым вызовом функции.

    Менять название переменной также разрешается:

    В этом примере a1, a2 и func имеют один и тот же id. Они ссылаются на один объект.

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

    Позже ее можно переименовать, используя более осмысленное имя. Первый вариант — просто сменить имя. Проблема в том, что если в другом месте кода используется sq , то этот участок не будет работать. Лучше просто добавить следующее выражение:

    Последний пример. Предположим, встроенная функция была переназначена:

    Теперь к ней нельзя получить доступ, а это может стать проблемой. Чтобы вернуть ее обратно, нужно просто удалить переменную:

    Анонимная функция: лямбда

    Лямбда-функция — это короткая однострочная функция, которой даже не нужно имя давать. Такие выражения содержат лишь одну инструкцию, поэтому, например, if , for и while использовать нельзя. Их также можно присваивать переменным:

    В отличие от функций, здесь не используется ключевое слово return . Результат работы и так возвращается.

    С помощью type() можно проверить тип:

    На практике эти функции редко используются. Это всего лишь элегантный способ записи, когда она содержит одну инструкцию.

    Изменяемые аргументы по умолчанию

    Читайте также: