Вебинары Разобраться в IT Реферальная программа
Программирование Аналитика Дизайн Маркетинг
07 Июл 2022
8 мин
20413

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

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

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

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

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

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

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

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

функции в Python

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

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

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

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

def addfunc(val1, val2):
    return val1 + val2

result = addfunc(3, 2)
print(result)
5

addfunc() # вызов без аргументов
Traceback (most recent call last):
...
TypeError: addfunc() missing 2 required positional arguments: 'val1' and 'val2'

addfunc(1) # вызов с одним аргументом
Traceback (most recent call last):
...
TypeError: addfunc() missing 1 required positional argument: 'val2'

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

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

def addconcat(*args):
    value = 0

    for item in args:
        if isinstance(item, (int, float)):
            value += item
        else:
            print(f"{item} is not a digit")

    return value

total = addconcat(1, "Hello", 2, 3, 4, "Python", 5.0, 6.25, 7.15, 'string')
Hello is not a digit
World is not a digit
string is not a digit

print("Total:", total)
Total: 28.4

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

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


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

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

def hey_concat(*args, name="World!"):
    print("Hey there,", name)

hey_concat()
Hey there, World!

hey_concat(name="Alex")
Hey there, Alex

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

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

def print_kwargs(**kwargs):
    print(kwargs) # отобразит словарь

print_kwargs(kone="One", ktwo=2, kthree=3.0)
{'kone': 'One', 'ktwo': 2, 'kthree': 3.0}

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

def kwargs_addconcat(**kwargs):

    a = kwargs.get("a", None)
    b = kwargs.get("b", None)

    if not isinstance(a, type(b)):
        raise TypeError("Ошибка! Разные типы")

    if isinstance(a, str):
        return f"Результат конкатенации строк\n{a + b}"

    elif isinstance(a, int):
        return f"Результат сложения чисел\n{a + b}"

    return "Ошибка"


print(kwargs_addconcat(a=1, b=2))
Результат сложения чисел
3

print(kwargs_addconcat(a=1, b="World!"))
...
TypeError: Ошибка! Разные типы

print(kwargs_addconcat(a="Hello, ", b="World!"))
Результат конкатенации строк
Hello, World!

# Без аргументов
print(kwargs_addconcat())
Ошибка

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

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

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

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

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

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

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

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

var1 = 12

def global_func():
    print(x)

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

✈️ Локальная

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

var1 = 2213 # глобальная переменная

# глобальная функция, использующая глобальную переменную
def func_one():
    print(var1)

# глобальная функция, использующая локальную переменную
def func_two():
    var1 = "Local value" # создание локальной переменной
    print(var1)

# функция, изменяющая значение глобальной переменной
def func_three():
    global var1
    var1 = "Local to global"

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

func_one()
2213

func_two()
Local value

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

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

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

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

def count_deco(wrapper_func):
    var = 0

    def inner():
        nonlocal var
        wrapper_func()
        var += 1
        print(var)
    return inner


@count_deco
def deco_demo():
    print("A few of example text...")


for _ in range(5):
    deco_demo()

A few of example text...
1
A few of example text...
2
A few of example text...
3
A few of example text...
4
A few of example text...
5

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

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

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

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

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

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

def arithmetics(x, y):
    return x + y, x - y, x * y, x / y, x // y

results = arithmetics(22, 3)

print(results)
(25, 19, 66, 7.333333333333333, 7)

print(results[0])
25

r1, r2, r3, r4, r5 = arithmetics(4, 4)

# результаты сложения и умножения
print(r1)
8

print(r3)
16

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

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

Эту функцию используют, чтобы создавать автоматические тесты, что здорово ускоряет и упрощает работу тестировщика. Научиться автоматизации можно на курсе Skypro «Инженер по тестированию». Опытные преподаватели-практики дадут всю необходимую теорию и помогут отработать знания на практических задачах.

QA-автоматизатор. Знакомство с Python. Урок 1

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

def gen_demo(times, var):
    for _ in range(times):
        yield var

gen_inst = gen_demo(25, "Gen demo text")

for _ in range(26):
    print(next(gen_inst))

Gen demo text
Gen demo text
Gen demo text
Gen demo text
...

Traceback (most recent call last):
...
StopIteration

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

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

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

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

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

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

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

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

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

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

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

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

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

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