Как сделать пустую переменную в python

Обновлено: 08.07.2024

Представьте себе задачу, нам нужно напечатать на экран фразу Father! два раза или даже пять раз. Эту задачу можно решить в лоб:

В простейшем случае так и стоит поступить, но если фраза Father! начнет использоваться чаще, да ещё и в разных частях программы, то придётся её везде повторять. Проблемы с таким подходом начнутся тогда, когда понадобится изменить нашу фразу, а такое происходит довольно часто. Нам придется найти все места где использовалось фраза Father! и выполнить необходимую замену. А можно поступить по другому. Вместо копирования нашего выражения, достаточно создать переменную с этой фразой.

В строчке greeting = 'Father!' - происходит присваивание значения 'Father!' переменной с именем greeting . Переменная указывает на данные, которые были в неё записаны. Благодаря этому, данные можно использовать многократно без необходимости их постоянно дублировать.

Когда переменная создана, можно начать её использовать. Она подставляется в те места, где раньше стояла наша фраза. Во время выполнения кода, интерпретатор (то, что выполняет код на Python), доходит до строчки print(greeting) и подставляет вместо переменной её содержимое, а затем выполняет код.

Для имени переменной используется любой набор допустимых символов, к которым относятся буквы английского алфавита, цифры и знак _ . При этом цифру нельзя ставить в начале. Имена переменных регистрозависимы, то есть имя hello и имя heLLo - это два разных имени, а значит и две переменные. Регистр в Python имеет важное значение, никогда не забывайте про него.

Количество создаваемых переменных никак не ограничено, большие программы содержат десятки и сотни тысяч имен переменных:

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

Изменение переменной

Само слово "переменная", говорит о том, что ее можно менять. И действительно, с течением времени внутри программы, значения переменных могут изменяться.

Имя осталось тем же, но внутри другие данные. Следует заметить, что переменные в Python не требуют специального объявления. Вместо этого переменная объявляется при первом её использовании в программе.

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

Ошибки при работе с переменными

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

Запуск программы, выше завершается с ошибкой NameError: name 'greeting' is not defined - это ошибка обращения, она означает, что в коде используется имя (говорят идентификатор), который не определен. Причём в самой ошибке об этом говорят прямо: 'greeting' is not defined . Кроме неправильного порядка определения, в Python встречаются банальные опечатки, причём как при использовании переменной, так и при её объявлении.

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

Выражения в определениях

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

Для начала переведем 50 евро в доллары. Допустим, что один евро — 1.25 долларов:

Выше мы записывали в переменную конкретное значение. А здесь dollars_count = 50 * 1.25 справа от знака равно находится выражение. Интерпретатор вычислит результат — 62.5 — и запишет его в переменную. С точки зрения интерпретатора не важно, что перед ним: 62.5 или 50 * 1.25 , для него оба варианта — выражения, которые надо вычислить. И они вычисляются в одно и тоже значение — 62.5 .

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

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

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

Основываясь на сказанном выше, подумайте, сработает ли такой код?

Запустите его на repl.it и поэкспериментируйте.

Вернемся к нашей валютной программе. Запишем стоимость доллара в рублях, как отдельную переменную. Вычислим цену 50 евро в долларах, умножив их на 1.25 . Допустим, что 1 доллар — 60 рублей:

А теперь давайте добавим к выводу текст с помощью конкатенации:

Любая переменная может быть частью любого выражения. В момент вычисления вместо имени переменной подставляется её значение.

Константы

Некоторые данные, такие как математические постоянные, никогда не меняются. Возьмем число π. Приближенно оно всегда равно 3.14 и не может измениться. Для обращения к подобным данным в Python принято использовать константы.

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

Интерполяция

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

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

Мы просто создали специальную строку ( template ) — так называемый "шаблон" — и разместили в ней несколько "пробелов" — пар фигурных скобок ( <> ). Затем с помощью применения операции .format() мы восполнили пробелы значениями переменных - по одной переменной на каждый "пробел" ( <> ). В одном шаблоне можно оставлять несколько "пробелов", но важно затем их заполнить все за один раз — подставить сразу нужное количество переменных.

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

Multi-line строки

Ещё один способ определения строк — это использование многострочных (multi-line) литералов. Для того, чтобы описать такую "многострочную строку", нужно заключить её в тройные кавычки - """ или ''' . Между парой таких тройных кавычек можно переносить текст со строки на строку и все переносы строк сохранятся.

Обратите внимание на то, что в конце текста есть пустая строка. Эта строка появилась в тексте потому, что мы поставили закрывающие кавычки ''' на новой строке. Если не переносить закрывающие кавычки на новую строку, эта пустая строка в тексте не появится.

Думайте о переменной как об имени, прикрепленном к определенному объекту. В Python переменные не нужно объявлять или определять заранее, как это имеет место во многих других языках программирования. Чтобы создать переменную, вы просто присваиваете ей значение, а затем начинаете использовать. Присваивание выполняется с помощью единственного знака равенства (=):

Так же, как буквальное значение может отображаться непосредственно из приглашения интерпретатора в сеансе REPL без необходимости print(), переменная может:

Позже, если вы измените значение n и используете его снова, вместо него будет подставлено новое значение:

Python также позволяет назначать цепочки, что позволяет назначать одно и то же значение нескольким переменным одновременно:

Цепное присвоение, приведенное выше, одновременно присваивает 300 переменных a, b и c.

Типы переменных в Python

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

Это ограничение не распространяется на переменные в Python. В Python переменной может быть присвоено значение одного типа, а затем повторно присвоено значение другого типа:

Ссылки на объекты

Что на самом деле происходит, когда вы присваиваете переменную? Это важный вопрос для Python, потому что ответ несколько отличается от того, что вы найдете во многих других языках программирования.

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

Рассмотрим этот код:

ри представлении оператора print (300) интерпретатор выполняет следующие действия:

  • Создает целочисленный объект
  • Придает ему значение 300
  • Отображает его на консоли

Вы можете видеть, что целочисленный объект создается с помощью встроенной функции type():

Переменная Python – это символическое имя, которое является ссылкой или указателем на объект. После того, как объект назначен переменной, вы можете ссылаться на объект по этому имени. Но сами данные все еще содержатся в объекте.

Это присвоение создает целочисленный объект со значением 300 и присваивает переменной n, указывающей на этот объект.

Variable reference diagram

Следующий код проверяет, что n указывает на целочисленный объект:

Теперь рассмотрим следующее утверждение:

Что происходит, когда он выполняется? Python не создает другой объект. Он просто создает новое символическое имя или ссылку, m, которая указывает на тот же объект, на который указывает n.

Python variable references to the same object (illustration)

Множественные ссылки на один объект

Далее предположим, что вы делаете это:

Теперь Python создает новый целочисленный объект со значением 400, и m становится ссылкой на него.

References to separate objects in Python (diagram)

Ссылки на отдельные объекты

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

Python variable reference illustration

Ссылка на целочисленный объект 300 больше не существует. Он потерян, и к нему невозможно получить доступ.

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

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

Идентичность объекта

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

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

После присвоения m = n , m и n оба указывают на один и тот же объект, что подтверждается тем фактом, что id (m) и id (n) возвращают одно и то же число. После переназначения m на 400, m и n указывают на разные объекты с разными идентификаторами.

Глубокое погружение: кэширование малых целочисленных значений

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

С оператором m = 300 Python создает целочисленный объект со значением 300 и устанавливает m в качестве ссылки на него. Затем n аналогичным образом присваивается целочисленному объекту со значением 300, но не тому же объекту. Таким образом, они имеют разные идентификаторы, что вы можете проверить по значениям, возвращаемым id() .

Здесь m и n по отдельности назначаются целочисленным объектам, имеющим значение 30. Но в этом случае id (m) и id (n) идентичны!

В целях оптимизации интерпретатор создает объекты для целых чисел в диапазоне [-5, 256] при запуске, а затем повторно использует их во время выполнения программы. Таким образом, когда вы назначаете отдельные переменные целочисленному значению в этом диапазоне, они фактически будут ссылаться на один и тот же объект.

Имена переменных

В примерах, которые вы видели до сих пор, использовались короткие, лаконичные имена переменных, такие как m и n. Но имена переменных могут быть более подробными. Фактически, это обычно полезно, потому что это делает назначение переменной более очевидным с первого взгляда.

Официально имена переменных в Python могут быть любой длины и могут состоять из прописных и строчных букв (A-Z, a-z), цифр (0-9) и символа подчеркивания (_). Дополнительным ограничением является то, что, хотя имя переменной может содержать цифры, первый символ имени переменной не может быть цифрой.

Примечание. Одним из дополнений к Python 3 была полная поддержка Unicode, которая также позволяет использовать символы Unicode в имени переменной. Вы узнаете о Unicode более подробно в одном из будущих руководств.

Например, все следующие допустимые имена переменных:

Но это не так, потому что имя переменной не может начинаться с цифры:

Обратите внимание, что регистр имеет значение. Строчные и прописные буквы – это не одно и то же. Также важно использование символа подчеркивания. Каждое из следующего определяет разные переменные:

Ничто не мешает вам создать две разные переменные в одной программе под названием age и Age, или, если на то пошло, agE. Но, вероятно, это опрометчиво. Это, безусловно, могло бы сбить с толку любого, кто пытается прочитать ваш код, и даже вас самого, после того, как вы какое-то время отдалились от него.

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

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

С другой стороны, не обязательно все они одинаково удобочитаемы. Как и во многих других случаях, это вопрос личных предпочтений, но большинство людей сочтут, что первые два примера, в которых все буквы сложены вместе, труднее читать, особенно букву, написанную заглавными буквами. Наиболее часто используемые методы построения имени переменной из нескольких слов – это последние три примера:

  • Camel Case: второе и последующие слова пишутся с заглавной буквы, чтобы границы слов было легче увидеть. (Предположительно, в какой-то момент кого-то поразило, что прописные буквы, разбросанные по всему имени переменной, отдаленно напоминают верблюжьи горбы.)
    • Пример: numberOfCollegeGraduates
    • Пример: NumberOfCollegeGraduates
    • Пример: number_of_college_graduates

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

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

    Руководство по стилю кода Python, также известное как PEP 8, содержит соглашения об именах, в которых перечислены рекомендуемые стандарты для имен различных типов объектов. PEP 8 включает следующие рекомендации:

    Зарезервированные слова (ключевые слова)

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

    В Python 3.6 есть 33 зарезервированных ключевых слова:

    Python
    Keywords
    False def if raise
    None del import return
    True elif in try
    and else is while
    as except lambda with
    assert finally nonlocal yield
    break for not
    class from or
    continue global pass

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

    Вывод

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

    Теперь вы хорошо разбираетесь в некоторых типах данных Python и знаете, как создавать переменные, которые ссылаются на объекты этих типов.

    Переменные в Python

    Статьи

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

    Введение

    Переменные — это зарезервированная область памяти для хранения данных. Это метки, которые прикрепляются к объектам и действуют как указатель или ссылка на объект. Например:

    Объявление переменной

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

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

    Правила объявления переменных:

    Преобразование типов

    • Неявное преобразование типов.
    • Явное преобразование типов.

    Область видимости

    В Python есть два типа переменных. Локальные и глобальные:

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

    Чтобы еще больше прояснить наше понимание области видимости переменных и переопределения, давайте рассмотрим этот пример:


    Заключение

    В этой статье вы узнали основы переменных Python.

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

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

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

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

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

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

    В Питоне есть множество встроенных в (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() просто выводит это значение пользователю и не влияет на дальнейшее исполнение кода, если он есть

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Функции создают не только через ключевое слово def и название функции. Можно использовать слово 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 , напомню, задает сортировку по убыванию.

    *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-функции.

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

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

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

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

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

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

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