07 Июл 2022
16 мин
629

Как использовать функции в Python

Любая функция начинается с инструкции def, названия и набора аргументов в скобках.

Содержание

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

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

Синтаксис функций в Python

Любые функции и методы начинаются с инструкции def (от английского define — «определять»). За def в Python идет название функции, после — набор аргументов. Двоеточие в конце открывает блок тела функции, которое располагают с новой строки. 

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

функции в Python

Аргументы и их виды

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

🚀 Позиционные

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

</p>
<p>def addfunc(val1, val2):<br />
return val1 + val2</p>
<p>result = addfunc(3, 2)<br />
print(result)<br />
5</p>
<p>addfunc() # вызов без аргументов<br />
Traceback (most recent call last):<br />
...<br />
TypeError: addfunc() missing 2 required positional arguments: 'val1' and 'val2'</p>
<p>addfunc(1) # вызов с одним аргументом<br />
Traceback (most recent call last):<br />
...<br />
TypeError: addfunc() missing 1 required positional argument: 'val2'</p>
<p>

Когда вызывают функцию addfunc, то передают ей два обязательных аргумента. Они  будут доступны внутри тела функции и ассоциированы с переменными val1 и val2. Если этого не сделаете, получите ошибку TypeError.

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

</p>
<p>def addconcat(*args):</p>
<p>    value = 0</p>
<p>    for item in args:</p>
<p>        if isinstance(item, (int, float)):</p>
<p>            value += item</p>
<p>        else:</p>
<p>            print(f"{item} is not a digit")</p>
<p>    return value</p>
<p>total = addconcat(1, "Hello", 2, 3, 4, "Python", 5.0, 6.25, 7.15, 'string')</p>
<p>Hello is not a digit</p>
<p>World is not a digit</p>
<p>string is not a digit</p>
<p>print("Total:", total)</p>
<p>Total: 28.4</p>
<p>

Обращаются к позиционному аргументу такого множества с помощью операции индексации:

</p>
<p>def demo_func(*args):</p>
<p>    try:</p>
<p>        print(args[0])</p>
<p>        print(args[1])</p>
<p>    except IndexError:</p>
<p>        pass</p>
<p>

🚀 Именованные

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

</p>
<p>def hey_concat(*args, name="World!"):</p>
<p>    print("Hey there,", name)</p>
<p>hey_concat()</p>
<p>Hey there, World!</p>
<p>hey_concat(name="Alex")</p>
<p>Hey there, Alex0</p>
<p>

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

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

</p>
<p>def print_kwargs(**kwargs):</p>
<p>    print(kwargs) # отобразит словарь</p>
<p>print_kwargs(kone="One", ktwo=2, kthree=3.0)</p>
<p>{'kone': 'One', 'ktwo': 2, 'kthree': 3.0}</p>
<p>

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

</p>
<p>def kwargs_addconcat(**kwargs):</p>
<p>    a = kwargs.get("a", None)</p>
<p>    b = kwargs.get("b", None)</p>
<p>    if not isinstance(a, type(b)):</p>
<p>        raise TypeError("Ошибка! Разные типы")</p>
<p>    if isinstance(a, str):</p>
<p>        return f"Результат конкатенации строк\n{a + b}"</p>
<p>    elif isinstance(a, int):</p>
<p>        return f"Результат сложения чисел\n{a + b}"</p>
<p>    return "Ошибка"</p>
<p>print(kwargs_addconcat(a=1, b=2))</p>
<p>Результат сложения чисел</p>
<p>3</p>
<p>print(kwargs_addconcat(a=1, b="World!"))</p>
<p>...</p>
<p>TypeError: Ошибка! Разные типы</p>
<p>print(kwargs_addconcat(a="Hello, ", b="World!"))</p>
<p>Результат конкатенации строк</p>
<p>Hello, World!</p>
<p># Без аргументов</p>
<p>print(kwargs_addconcat())</p>
<p>Ошибка</p>
<p>

В примере упаковываем именованные аргументы в переменную с названием kwargs. Из нее в теле функции по ключам a и b пытаемся получить значения. А если они не найдутся — объект None. Далее проверяем наличие обоих аргументов и принадлежность одному типу данных. Затем возвращаем результат выполнения в зависимости от типа переданных параметров.

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

Общая форма последовательности:

</p>
<p>def func(a, b, *args, name="Default", **kwargs):</p>
<p>    return None</p>
<p>

Функции и области видимости

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

✈️ Глобальная

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

</p>
<p>var1 = 12</p>
<p>def global_func():</p>
<p>    print(x)</p>
<p>

Здесь целочисленный объект var1 и функция global_func — в глобальной области видимости.

✈️ Локальная

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

</p>
<p>var1 = 2213 # глобальная переменная</p>
<p># глобальная функция, использующая глобальную переменную</p>
<p>def func_one():</p>
<p>    print(var1)</p>
<p># глобальная функция, использующая локальную переменную</p>
<p>def func_two():</p>
<p>    var1 = "Local value" # создание локальной переменной</p>
<p>    print(var1)</p>
<p># функция, изменяющая значение глобальной переменной</p>
<p>def func_three():</p>
<p>    global var1</p>
<p>    var1 = "Local to global"</p>
<p>

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

</p>
<p>func_one()</p>
<p>2213</p>
<p>func_two()</p>
<p>Local value</p>
<p>func_three() # функция меняет значение глобальной переменной</p>
<p>func_one() # и результат функции func_one</p>
<p>Local to global</p>
<p>

✈️ Область объемлющих функций

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

Так реализуют декоратор счетчика вызова функции Python с этим ключевым словом:

</p>
<p>def count_deco(wrapper_func):</p>
<p>    var = 0</p>
<p>    def inner():</p>
<p>        nonlocal var</p>
<p>        wrapper_func()</p>
<p>        var += 1</p>
<p>        print(var)</p>
<p>    return inner</p>
<p>@count_deco</p>
<p>def deco_demo():</p>
<p>    print("A few of example text...")</p>
<p>for _ in range(5):</p>
<p>    deco_demo()</p>
<p>A few of example text...</p>
<p>1</p>
<p>A few of example text...</p>
<p>2</p>
<p>A few of example text...</p>
<p>3</p>
<p>A few of example text...</p>
<p>4</p>
<p>A few of example text...</p>
<p>5</p>
<p>

Lambda-функции (анонимные)

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

</p>
<p>list_values = [1, 3, 4, 2, 6, 7, 5, 8, 9]</p>
<p>filter(lambda x : x % 2 == 0, list_values)</p>
<p>[2, 4, 6, 8]</p>
<p>

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

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

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

</p>
<p>def arithmetics(x, y):</p>
<p>    return x + y, x - y, x * y, x / y, x // y</p>
<p>results = arithmetics(22, 3)</p>
<p>print(results)</p>
<p>(25, 19, 66, 7.333333333333333, 7)</p>
<p>print(results[0])</p>
<p>25</p>
<p>r1, r2, r3, r4, r5 = arithmetics(4, 4)</p>
<p># результаты сложения и умножения</p>
<p>print(r1)</p>
<p>8</p>
<p>print(r3)</p>
<p>16</p>
<p>

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

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

Чтобы передать аргументы генератору и вернуть значения, применяют ключевое слово yield. Когда элементы объекта-генератора заканчиваются, тот возбуждает исключение типа StopIteration:

</p>
<p>def gen_demo(times, var):</p>
<p>    for _ in range(times):</p>
<p>        yield var</p>
<p>gen_inst = gen_demo(25, "Gen demo text")</p>
<p>for _ in range(26):</p>
<p>    print(next(gen_inst))</p>
<p>Gen demo text</p>
<p>Gen demo text</p>
<p>Gen demo text</p>
<p>Gen demo text</p>
<p>...</p>
<p>Traceback (most recent call last):</p>
<p>...</p>
<p>StopIteration</p>
<p>

[FAQ] Частые вопросы

Функции vs процедуры — в чём отличие?

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

Для чего нужна область видимости? 

Чтобы решить конфликт имен.

Как провести распаковку множества? 

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

Обязательно ли наличие аргументов для функции? 

Нет, но чаще у функции есть один или несколько аргументов.

Главное о функциях в Python

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

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

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


Получите пошаговый план развития в карьере после записи на курс






    Оставляя заявку, вы принимаете условия соглашения

    Учёба ради учёбы — это не прикольно. На наших курсах вы ставите конкретные цели и достигаете
    их
    в заданные сроки. Начинайте карьеру с первых достижений!

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

    Вставить формулу как
    Блок
    Строка
    Дополнительные настройки
    Цвет формулы
    Цвет текста
    #333333
    Используйте LaTeX для набора формулы
    Предпросмотр
    \({}\)
    Формула не набрана
    Вставить