Как вызвать функцию без декоратора python
Перейти к содержимому

Как вызвать функцию без декоратора python

  • автор:

Русские Блоги

Функция обратного вызова Python и функция украшения

1. Функция обратного вызова

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

  • Синхронный вызов — это блокирующий вызов, вызывающий должен дождаться завершения другой стороны, прежде чем вернуться, это односторонний вызов;
  • Обратный вызов — это режим двустороннего вызова, то есть вызываемый также будет вызывать интерфейс другой стороны при вызове интерфейса;
  • Асинхронный вызов — это механизм, похожий на сообщения или события, но его направление вызова прямо противоположное.Когда происходит определенное сообщение или событие, служба интерфейса будет активно уведомлять клиента (то есть вызывать интерфейс клиента.

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

2. Функция украшения

Один). Назначение функции украшения

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

Два). Прошлое и настоящее декоратора.

1. Доисторические истории

Давайте сначала рассмотрим простой пример, который на самом деле может быть намного сложнее:

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

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

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

2. Разрушить мир

Вышесказанное тоже принцип декораторов! ! !

3. Предварительное исследование мира питонов.

@ Syntax Sugar
Если вы какое-то время контактировали с Python, вы должны быть знакомы с символом @. Да, символ @ является синтаксическим сахаром для декораторов. Он помещается в начало определение функции, поэтому вы можете пропустить последнюю операцию одношагового переназначения

С помощью @ мы можем опустить предложение today = logging_tool (today) и вызвать today () напрямую, чтобы получить желаемый результат.
Не нужно изменять функцию today (), просто добавьте декоратор там, где он определен., Звонок по-прежнему такой же, как и раньше.
Если у нас есть другие похожие функции, мы можем продолжать вызывать декоратор для украшения функции., Вместо того, чтобы многократно изменять функции или добавлять новые пакеты. Таким образом улучшается возможность повторного использования программы и повышается удобочитаемость программы.

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

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

4. Сотни разноплановых научных школ утверждают, что
1). Декоратор с параметрами

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

2). Пусть декоратор поддерживает как с параметрами, так и без них.

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

3). Декоратор классов

Декораторы могут быть не только функциями, но и классами.По сравнению с декораторами функций, декораторы классов обладают преимуществами большей гибкости, высокой связности и инкапсуляции. Использование декораторов классов в основном зависит от метода вызова класса. Этот метод будет вызываться, когда декоратор присоединяется к функции с помощью формы @.

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

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

4). Функция украшения -> Класс украшения
  • Декораторы на уровне функций очень распространены, они принимают функцию в качестве входных и возвращают новую функцию;
  • Декорация на уровне класса фактически аналогична, с классом в качестве входных данных, и возвращается новый класс;

Например: добавьте свойство длины и методы получения и установки к существующему классу.

5. Древние артефакты
1) @property -> метод получения / установки

Пример: добавьте к учащемуся методы получения и установки атрибута score.

2). @classmethod、@staticmethod
  • Метод класса @classmethod: определите альтернативные конструкторы, первый параметр — это сам класс (имя параметра не ограничено, обычно используется cls)
  • @staticmethod Статический метод: функция, тесно связанная с классом

Пример простого принципа:

3)[email protected]

Декоратор многократно использует код, но у него есть недостаток: поскольку он возвращает оболочку вложенного объекта функции, а не исходную функцию, теряется метаинформация исходной функции, такая как строка документации функции, имя, список параметров и другая информация. . Однако решение сложнее, чем есть на самом деле. Мы можем скопировать метаинформацию исходной функции в функцию func в декораторе через @ functools.wraps, чтобы функция в декораторе имела ту же метаинформацию, что и оригинальная функция.

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

4).Easter egg
  • Определите оболочку, которая принимает параметры

То есть: возвращаемый результат декоратора (x, y, z) должен быть вызываемым объектом, который принимает функцию в качестве параметра и обертывает ее.

  • Функция может определять несколько декораторов одновременно, например:

То есть: порядок его выполнения — изнутри наружу, самый внутренний слой вызывается первым, а самый внешний декоратор вызывается последним.

Декораторы в Python: понятие, структура, примеры использования

Smartiqa Article docker

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

Когда исполняется код, объявленные в нем переменные и объекты могут иметь сложную внутреннюю структуру. Питон понимает, как их обнаруживать, в каком порядке вызывать и возвращать. Существенный момент здесь — области видимости.

Например, вы в своем скрипте объявили переменную number, а где-то в другом месте этого файла вызывается функция, внутри которой есть своя переменная с таким же именем. Более того, никто не даст гарантию, что импортируемый модуль не содержит в себе аналогичное наименование. Такие ситуации не столь редки, как может показаться, следовательно, требуется ознакомиться с областями видимости в Python.

Всего их имеется 3 (от высшей к низшей):
— встроенная,
— на уровне модуля,
— локальная.

Rukovodstvo

статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.

Введение в декораторы Python

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

Время чтения: 5 мин.

Вступление

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

В этой статье мы подробно обсудим декораторы Python.

Как создавать декораторы

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

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

Выход

Обратите внимание, что вы можете объединить два вышеуказанных фрагмента кода в один. Мы создали функцию hello_function() которая возвращает предложение «ПРИВЕТ, МИР». Затем мы вызвали декоратор и передали имя этой функции в качестве аргумента, присвоив его переменной decorate. После выполнения вы можете увидеть, что полученное предложение было преобразовано в нижний регистр.

Однако в Python есть более простой способ применения декораторов. Мы можем просто добавить @ перед именем функции-декоратора прямо над функцией, которую нужно оформить. Например:

Выход

Как применить несколько декораторов к функции

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

Здесь мы создали декоратор, который берет входное предложение и разбивает его на различные части. Декоратору было присвоено имя split_sentence . Теперь применим lowercase и split_sentence к одной функции.

Чтобы выполнить эти операции в правильном порядке, примените их следующим образом:

Выход

Наше предложение было разделено на две части и преобразовано в нижний регистр, так как мы применили декораторы lowercase и split_sentence hello_function .

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

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

Выход

В приведенном выше сценарии декоратор принимает два аргумента: argument1 и argument1 .

Создание декораторов общего назначения

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

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

Выход

Как видите, декоратору не было передано никаких аргументов.

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

Выход

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

Выход

В декоратор были переданы два аргумента ключевого слова.

В следующем разделе мы обсудим, как отлаживать декораторы.

Как отлаживать декораторы

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

Например: если мы попытаемся получить метаданные для декоратора function_with_arguments , мы получим метаданные закрытия оболочки. Продемонстрируем это:

Выход

Это представляет собой большую проблему во время отладки. Однако Python предоставляет functools.wraps который может помочь в решении этой проблемы. Он работает путем копирования потерянных метаданных на вашу декорированную крышку.

Теперь давайте продемонстрируем, как это работает:

Выход

Поскольку мы использовали functools.wraps для функции-оболочки, мы можем проверить метаданные функции на "hello_function":

Выход

Выход

Приведенный выше сценарий ясно показывает, что метаданные теперь относятся к функции, а не к оболочке. Я рекомендую вам всегда использовать functools.wraps каждый раз, когда вы определяете декоратор. Это значительно упростит вам отладку.

Заключение

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

Функции в Питоне

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

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

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

Встроенные функции

В Питоне есть множество встроенных в (1) стандартный функционал (built-in functions) и (2) дополнительные библиотеки (library functions) функций, и мы много раз их использовали.

Рассмотрим функцию для создания гистограммы plt.hist(). Вначале импортируем библиотеки.

Сгенерируем данные, которые передадим этой функции (эти же данные мы создавали и использовали на восьмом занятии вводного курса).

Теперь построим гистограмму передав ей в качестве параметров и аргументов наши данные и количество интервалов.

параметры функции plt.hist()

Как мы видим, достаточно обратиться к соответствующей библиотеке ( plt ), вызвать эту функцию по имени ( hist ) и задать параметры и их аргументы ( height и bins = 10 ), и будет исполнен тот код, который заложили в нее создатели библиотеки Matplotlib.

Теперь несколько слов про параметры и аргументы функции.

Параметры и аргументы функции

Для начала определимся с терминами:

  • параметр — это то, что запрашивает функция при вызове (например, bins , количество интервалов)
  • аргумент — значение этого параметра (в нашем случае, 10 ).

Возникает вопрос, что же такое height ? Логично предположить, что это аргумент (ведь это наши данные). Но тогда как функция узнает, какому параметру он соответствует?

Все дело в том, что параметры и их аргументы могут быть позиционными (positional) и именованными (keyword).

позиционные и именованные аргументы функции

В первом случае, достаточно указать аргумент и поставить его в правильном порядке (позиции). Функция сама поймет, какой параметр ей передают. Во втором случае, нужно указать и название параметра, и аргумент.

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

использование именованных параметров функции plt.hist()

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

аргументы по умолчанию функции plt.hist()

Как вы видите, результат во всех трех случаях совершенно одинаковый.

Если вы сомневаетесь в том, какие параметры принимает функция и что является результатом ее работы, полезно обратиться к документации в Интернете. Например, по функции plt.hist() ее можно найти вот здесь⧉.

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

Функции и методы

Некоторые функции называются методами. Методы — это функции, которые можно применить только к конкретному объекту. Другими словами, если обычная функция будет выполнена «сама по себе», это просто участок кода, которому дали имя, то методу для исполнения нужен объект (например, строка, список или словарь). При этом, что важно, у каждого объекта свои методы.

Предположим, у нас есть строка, и мы хотим сделать первую букву каждого слова заглавной. Для этого у строки есть метод .title().

А теперь попробуем применить этот метод к списку, состоящему из тех же слов, что и строка.

ошибка при применении строкового метода .title() к списку

Как мы видим, Питон выдал ошибку.

Собственные функции в Питоне

Объявление и вызов функции

Функции не обязательно должны быть встроены в базовый функционал или библиотеки. Мы вполне можем объявлять (т.е. создавать) собственные функции (user-defined functions). Рассмотрим пример.

Теперь давайте разберем каждый элемент этого кода. Вначале посмотрим как объявить функцию (declare a function).

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

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

вызов собственной функции

Пустое тело функции

Оставлять тело функции совсем пустым нельзя. Нужно как минимум указать ключевое слово return или оператор pass.

Хотя может показаться, что в этом случае функция ничего не выдает, на самом деле это не так. И в том, и в другом случае функция возвращает особый тип данных None (отсутствие значения).

Функция print() вместо return

Помимо ключевого слова return, результат работы функции можно вывести с помощью print().

Хотя визуально вывод идентичен, отличие все-таки есть:

  • Использование return возвращает значение функции (в нашем случае значение переменной res) и прерывает ее работу
  • Функция print() просто выводит это значение пользователю и не влияет на дальнейшее исполнение кода, если он есть

Параметры собственных функций

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

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

И конечно функция может изначально не иметь параметров.

Аннотация функции

Аннотация функции (function annotation) позволяет явно прописать тип данных параметров (parameter annotation) и возвращаемых значений (return annotation).

Аннотация не является обязательной и никак не вляет на выполнение кода.

Дополнительные возможности функций

Вызов функции можно совмещать с арифметическими операциями.

Доступны и логические операции.

Если результатом вывода является строка, то у этой строки также есть индекс.

Функция может не использовать параметры, но получать данные от пользователя через input().

Появится окно для ввода числа.

функция может получать данные от пользователя

Введем число пять и посмотрим на результат.

Результат вызова функции

Функция не обязательно возвращает только число или строку, это может быть, в частности, список, кортеж или словарь. Рассмотрим несколько примеров.

Функция может возвращать сразу несколько значений.

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

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

Функция может возвращать и логическое значение. Давайте объявим функцию, которая проверяет четное ли ей передали число (и в этом случае вернет True) или нечетное (и тогда False).

Использование библиотек

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

Глобальные и локальные переменные

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

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

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

ошибка при вызове локальной переменной вне своей функции

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

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

Функция всегда «предпочтет» содержащуюся в ней локальную переменную.

При этом значение глобальной переменной для остального кода не изменится.

Анонимные или lambda-функции

Функции создают не только через ключевое слово def и название функции. Можно использовать слово lambda и вообще обойтись без названия. Приведем простой пример.

Теперь давайте в деталях рассмотрим, как мы получили такой результат.

  • вначале ставится ключевое слово lambda
  • за ним идут передаваемые параметры
  • через двоеточие пишется исполняемое выражение

Разумеется, ничто не мешает поместить этот же функционал в обычную функцию.

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

Lambda-функция внутри функции filter()

Предположим, у нас есть список чисел, и мы хотим оставить в нем только те числа, которые больше 10. Давайте решим эту задачу с помощью функции filter() и lambda-функции.

Функция filter() принимает два параметра:

  • Во-первых, еще одну функцию, выполняющую роль критерия; она выдает True , если элемент нужно оставить, и False — если убрать
  • Во-вторых, набор элементов, которые нужно отфильтровать в виде списка, кортежа или множества

Получив их, filter() применяет критерий (функцию) к каждому из элементов набора.

Посмотрим на реализацию на Питоне. Вначале создадим список.

Теперь зададим фильтрующую lambda-функцию.

После этого поместим criterion и nums в функцию filter(). Так как сама функция filter() вернет нам не список, а специальный объект iterator, его в свою очередь нужно преобразовать обратно в список с помощью функции list().

Чаще такой функционал записывают в одну строчку.

И в этом и заключается удобство lambda-функции, ее не надо объявлять заранее. Через обычную функцию код выглядел бы так.

Lambda-функция внутри функции sorted()

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

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

Затем мы захотели отсортировать этот список по расстоянию, то есть по второму элементу кортежа.

Мы взяли функцию sorted() и в качестве параметра ключа, по которому сортировать список (key), передали ей lambda-функцию, принимающей кортеж из двух элементов на входе, и выдающей второй его элемент на выходе.

Параметр reverse = True , напомню, задает сортировку по убыванию.

Немедленно вызываемые функции

Lambda-функции относятся к так называемым немедленно вызываемым функциям или immediately invoked function expressions (IIFE). Это означает, что мы можем одновременно объявить и вызвать такую функцию.

*args и **kwargs

Прежде чем завершить, поговорим про еще одну важную тему, а именно про так называемые *args (сокращение от arguments) и **kwargs (keyword arguments).

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

Рассмотрим на примере. Начнем с *args.

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

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

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

ошибка при использовании *args

*args позволяет передавать функции произвольное количество отдельных чисел.

Как вы видите, главным элементом здесь является оператор распаковки * (unpacking operator). Он принимает все передаваемые в функцию числа и формирует из них кортеж.

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

Если мы по какой-то причине захотим передать функции список, мы можем это сделать.

В этом случае мы передаем название списка со звездочкой *.

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

**kwargs

При использовании **kwargs происходит почти то же самое за тем исключением, что мы распаковываем именованные, а не позиционные аргументы. И распаковываем их в словарь, а не в список. Сразу посмотрим на примере.

Приведем более сложный пример. Напишем функцию, которая на вход примет произвольное количество чисел (позиционный аргумент), преобразует в кортеж (*args) и рассчитает среднее арифметическое (mean) и среднее квадратическое отклонение (standard deviation).

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

Вызовем функцию simple_stats() и передадим ей числа и именованные аргументы.

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

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

Количество именованных аргументов в **kwargs может быть любым. Ничто не мешает нам добавить еще один параметр.

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

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

Подведем итог

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

  • использовать готовые функции, которые уже встроены либо в базовый функционал, либо в дополнительную библиотеку;
  • объявлять собственные функции через ключевое слово def и название функции; а также
  • создавать анонимные или lambda-функции, которые очень удобно применять там, где в полноценных собственных функциях нет необходимости

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

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

Наконец, мы поговорили про возможность передачи различного количества позиционных и именованных аргументов через *args и **kwargs.

Вопросы для закрепления

Какие три вида функций мы изучили?

Посмотреть правильный ответ

Ответ: встроенные, собственные, а также анонимные или lambda-функции.

Какие бывают параметры и аргументы функции?

Посмотреть правильный ответ

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

Какова область видимости локальной переменной?

Посмотреть правильный ответ

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

В ноутбуке к лекции приведены дополнительные упражнения⧉.

В следующий раз мы подробнее рассмотрим списки, кортежи и множества.

Ответы на вопросы

Вопрос. Скажите, а почему используется символ нижнего подчеркивания в названии переменной list_?

Ответ. Не стоит использовать просто list для именования переменных, потому что это слово зарезервировано для названия функции. Аналогично не стоит использовать dict, tuple, set и т.д. При этом некоторые слова использовать в качестве названия переменных просто не получится. Питон выдаст ошибку. Это, например, if, for, True, False, import и т.п.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *