🐍 Самоучитель по Python для начинающих. Часть 11: Функции с позиционными и именованными аргументами
Разберемся, как передавать в функцию произвольное число аргументов, как задавать и изменять параметры по умолчанию, и как возвращать результаты работы в основную программу. В конце статьи – 10 практических задач.
Функция – это мини-программа внутри основной программы. Код такой подпрограммы отвечает за решение определенной задачи: например, в игре Тетрис будут отдельные функции для подсчета очков, рисования игрового поля, движения фигурки и так далее. Использование функций позволяет:
- ограничить область видимости переменных функциями, которые их используют;
- исключить дублирование кода;
- разбить большую и сложную программу на небольшие мини-программы, которые можно вызывать в нужный момент;
- выстроить простую и понятную структуру программы – такой код удобнее дебажить и поддерживать.
У функций есть несколько особенностей:
- Функция выполняется только тогда, когда ее вызывает основная программа.
- В функцию можно передавать различные данные. Параметры – это переменные, которые используются при объявлении функции, аргументы – фактические значения, которые передаются переменным при вызове функции.
- Функции могут передавать результаты своей работы в основную программу или в другие функции.
Функции в Python
Python работает со встроенными и пользовательскими функциями. Встроенные функции – это уже знакомые нам print(), input(), map(), zip() и так далее. Пользовательские функции, в свою очередь, делятся на:
- Рекурсивные (вызывают сами себя до тех пор, пока не будет достигнут нужный результат).
- Анонимные, или лямбда-функции (объявляются в любом участке кода и сразу же вызываются).
- Все остальные функции, которые определены пользователем и не относятся ни к рекурсивным, ни к анонимным.
В этой статье мы рассмотрим пользовательские функции с различными типами параметров, а в последующих статьях разберем анонимные и рекурсивные функции.
Объявление и вызов функций в Python
Для создания функции используют ключевое слово def
. Вот пример простейшей функции, которая не получает и не возвращает никаких данных – просто выполняет одну команду по выводу строки с приветствием:
def my_function(): print('Привет от Python')
Для вызова такой функции достаточно написать ее название:
my_function()
Результат вызова:
Привет от Python
А это пример простейшей функции с параметром:
def my_function(name): print(f'Привет, {name}')
При вызове функция получает аргумент:
my_function('Вася')
Результат вызова:
Привет, Вася
При вызове функция ожидает получить набор значений, соответствующий числу параметров. К примеру, эта функция должна получить при вызове два позиционных аргумента – имя и фамилию:
def my_function(name, lastname): print(f'Добрый день, {name} {lastname}')
Если передать в функцию два аргумента – my_function('Егор', 'Куликов')
, результат вызова будет таким:
Добрый день, Егор Куликов
Но если число аргументов окажется меньше числа параметров – my_function('Алена')
, возникнет ошибка:
my_function('Алена') TypeError: my_function() missing 1 required positional argument: 'lastname'
Порядок обработки позиционных аргументов
Python обрабатывает позиционные аргументы слева направо:
def my_function(name, last_name, occupation, age): print(f'Сотрудник #1 - {name} {last_name} {occupation} {age}') info1, info2, info3, info4 = 'Алиса', 'Селезнева', 'скрам-мастер', 30 my_function(info1, info2, info3, info4) my_function(info2, info3, info1, info4) my_function(info4, info1, info2, info3)
Вывод:
Сотрудник #1 - Алиса Селезнева скрам-мастер 30 Сотрудник #1 - Селезнева скрам-мастер Алиса 30 Сотрудник #1 - 30 Алиса Селезнева скрам-мастер
Аргументы по умолчанию
Функция может использовать аргументы по умолчанию – они указываются после позиционных:
def my_function(strt, build, ap, city='Москва'): print(f'Адрес: г.{city}, ул.{strt}, д.{build}, кв.{ap}') my_function('Красная', '5', '3', 'Тула') my_function('Красная', '5', '3') Результат: Адрес: г.Тула, ул.Красная, д.5, кв.3 Адрес: г.Москва, ул.Красная, д.5, кв.3
Именованные аргументы
Помимо позиционных, в функцию можно передать именованные аргументы, причем порядок передачи именованных аргументов при вызове функции может не совпадать с порядком параметров:
def sales_price(price, discount=5): return price - price * discount / 100 print(sales_price(5000)) print(sales_price(5000, discount=10)) print(sales_price(discount=15, price=5000))
Вывод:
4750.0 4500.0 4250.0
Произвольное количество позиционных аргументов *args
До сих пор мы передавали в функцию определенное, заранее известное число позиционных аргументов. Если в функцию нужно передать произвольное количество
аргументов, используют *args
:
def my_function(*args): print(f'Минимальное число: {min(args)}, максимальное: {max(args)}') my_function(1, 4, 5, 2, -5, 0, 12, 11)
Результат вызова:
Минимальное число: -5, максимальное: 12
При использовании *args
функция получает кортеж аргументов, и к ним можно обращаться так же, как к элементам кортежа:
def my_function(*args): print(f'Первое слово: {args[0]}, последнее слово: {args[-1]}') my_function('яблоко', 'виноград', 'апельсин', 'арбуз', 'слива', 'груша')
Результат вызова:
Первое слово: яблоко, последнее слово: груша
Название набора параметров, *args, используется по умолчанию. При
желании его можно изменить на любое другое название с *
в начале:
def my_function(*cities): print(f'Первый город: {cities[0]}, третий город: {cities[2]}') my_function('Тюмень', 'Москва', 'Орел', 'Новгород', 'Ижевск', 'Ульяновск')
Результат вызова:
Первый город: Тюмень, третий город: Орел
Аргументы *args
обрабатываются после позиционных, но до аргументов по умолчанию:
def my_function(x, y, *args, kx=15, ky=15): print(x, y, args, kx, ky) my_function(5, 6, 7, 8, 9, 0, 4)
Вывод:
5 6 (7, 8, 9, 0, 4) 15 15
Произвольное количество именованных аргументов **kwargs
Как уже было отмечено выше, именованные аргументы передаются в функцию в виде пар ключ=значение
:
def my_function(cat1, cat2, cat3): print(f'Младший кот: {cat1}, старший кот: {cat2}') my_function(cat1='Том', cat2='Барсик', cat3='Полосатик')
Результат вызова:
Младший кот: Том, старший кот: Барсик
В приведенном выше примере количество именованных аргументов известно заранее. Если в функцию нужно передать произвольное количество пар
ключ=значение
, используют параметр **kwargs
. С **kwargs
работают все методы словарей:
def my_function(**kwargs): print(f'Самый легкий металл - {min(kwargs, key=kwargs.get)} {min(kwargs.values())}, самый тяжелый - {max(kwargs, key=kwargs.get)} {max(kwargs.values())}') my_function(осмий=22.61, цинк=7.1, золото=19.3, ртуть=13.6, олово=7.3)
Результат вызова:
Самый легкий металл - цинк 7.1, самый тяжелый - осмий 22.61
Как и в случае с *args, название по умолчанию **kwargs при желании можно заменить на любое другое с **
в начале:
def my_function(**countries): print(f'Самая густонаселенная страна - {max(countries, key=countries.get)} {max(countries.values())} чел/км2, самая малонаселенная - {min(countries, key=countries.get)} {min(countries.values())} чел/км2') my_function(Мальта=1432, Дания=128, Монако=18679, Индия=357, Монголия=2)
Результат вызова:
Самая густонаселенная страна - Монако 18679 чел/км2, самая малонаселенная - Монголия 2 чел/км2
Аргументы типа **kwargs
обрабатываются после позиционных, *args
и аргументов по умолчанию:
def my_function(x, y, *args, kx=15, ky=15, **kwargs): print(x, y, args, kx, ky, kwargs) my_function(7, 8, 0, 3, 4, 1, 8, 9, север=15, запад=25, восток=45, юг=10)
Вывод:
7 8 (0, 3, 4, 1, 8, 9) 15 15 {'север': 15, 'запад': 25, 'восток': 45, 'юг': 10}
Передача аргументов в виде списка
Помимо кортежей и словарей, в функции можно передавать списки:
def my_function(stationery): for i, j in enumerate(stationery): print(f'Товар #{i + 1} - {j}') stuff = ['карандаш', 'ручка', 'блокнот', 'альбом', 'тетрадь', 'ластик'] my_function(stuff)
Результат вызова:
Товар #1 - карандаш Товар #2 - ручка Товар #3 - блокнот Товар #4 - альбом Товар #5 - тетрадь Товар #6 - ластик
Заглушка pass
Тело функции не может быть пустым – это приведет к сообщению об ошибке:
def my_function(): Вывод: def my_function(): ^ SyntaxError: unexpected EOF while parsing
Если по какой-то причине нужно оставить тело функции пустым, используют оператор pass
, который выступает в роли заглушки:
def my_function(): pass
Функции с возвратом значений
Как уже было показано выше, функции могут получать и обрабатывать любые типы данных – строки, числа, списки, кортежи, словари. Результат обработки можно получить с помощью оператора return. Эта функция возвращает произведение произвольного количества значений:
def my_function(*args): prod = 1 for i in args: prod *= i return prod print(my_function(5, 6, 3, 11))
Значения передаются в функцию при вызове – print(my_function(5, 6, 3, 11))
. Результат при таком наборе цифр будет равен 990
. Оператор return может возвращать любое количество значений, причем значения возвращаются в виде кортежа:
def calculations(a, b): summa = a + b diff = a - b mul = a * b div = a / b return summa, diff, mul, div num1, num2 = int(input()), int(input()) summa, diff, mul, div = calculations(num1, num2) print( f'Сумма: {summa}\n' f'Разница: {diff}\n' f'Произведение: {mul}\n' f'Результат деления: {div:.2f}\n' )
Пример ввода:
49 6
Вывод:
Сумма: 55 Разница: 43 Произведение: 294 Результат деления: 8.17
Функция может содержать любое количество return
. Эта функция возвращает различные оценки индекса массы тела:
def bmi(h, w): bmi = w / (h / 100) ** 2 if bmi <= 18.5: return 'У вас дефицит веса' elif bmi <= 24.9: return 'Вес в норме' elif bmi <= 29.9: return 'Есть лишний вес' else: return 'Срочно на диету!' h = float(input('Введите рост в см: ')) w = float(input('Введите вес в кг: ')) print(bmi(h, w))
Пример ввода:
Введите рост в см: 172 Введите вес в кг: 61
Вывод:
Вес в норме
Однако эту функцию можно переписать так, чтобы использовался только один оператор return
:
def bmi(h, w): bmi = w / (h / 100) ** 2 if bmi <= 18.5: res = 'У вас дефицит веса' elif bmi <= 24.9: res = 'Вес в норме' elif bmi <= 29.9: res = 'Есть лишний вес' else: res = 'Срочно на диету!' return res h = float(input('Введите рост в см: ')) w = float(input('Введите вес в кг: ')) print(bmi(h, w))
Практика
Задание 1
Напишите функцию для вывода треугольника. Функция принимает два аргумента – size (размер сторон треугольника) и symb (символ, используемый для заполнения треугольника).
Пример ввода:
9 .
Вывод:
. .. ... .... ..... .... ... .. .
Решение:
def draw_triangle(size, symb): for i in range(1, size + 1): print(symb * min(i, size - i + 1)) size, symb = int(input()), input() draw_triangle(size, symb)
Задание 2
Напишите функцию, которая принимает произвольное количество
целых чисел, и возвращает среднее арифметическое без использования встроенных
функции sum()
и len()
.
Пример вызова:
print(arith_mean(5, 5, 15, 25, 35))
Вывод:
17.0
Решение:
def arith_mean(*args): summa = 0 kol = 0 for i in args: summa += i kol += 1 return summa / kol
Задание 3
Напишите функцию, которая:
- принимает строку, состоящую из букв, цифр и специальных символов;
- формирует три списка – 1) из цифр, 2) из букв, 3) из спецсимволов;
- выводит списки на экран.
Пример ввода:
23edwd893rjf934#$%Ye34F^(*))_+W$#Ddq2ddscew3r
Вывод:
2 3 8 9 3 9 3 4 3 4 2 3 e d w d r j f Y e F W D d q d d s c e w r # $ % ^ ( * ) ) _ + $ #
Решение:
def sort_list(st): digits = [i for i in st if i.isdigit()] letters = [i for i in st if i.isalpha()] spec_char = [i for i in st if not i.isalnum()] print(*digits) print(*letters) print(*spec_char) my_st = input() sort_list(my_st)
Задание 4
Напишите функцию, которая начисляет новогодние премии сотрудникам. Эта функция:
- имеет два аргумента по умолчанию –
salary=120000
иbonus=10
(оклад и премия); - получает два позиционных аргумента
name
иlast_name
– имя и фамилию сотрудника; - учитывает индивидуальные оклад и премию (см. примеры вызова);
- выводит размер новогодней премии для сотрудника и зарплату с учетом премии.
Примеры вызова функции:
ny_bonus('Алина', 'Тимофеева', salary=150000, bonus=25) ny_bonus('Алексей', 'Ковалев', bonus=15) ny_bonus('Игорь', 'Ефимов') ny_bonus('Анастасия', 'Яковлева', salary=100000, bonus=20)
Вывод:
Новогодняя премия сотрудника Алина Тимофеева: 37500.00 руб. Оклад: 150000.00 руб. Всего к выдаче: 187500.00 руб. Новогодняя премия сотрудника Алексей Ковалев: 18000.00 руб. Оклад: 120000.00 руб. Всего к выдаче: 138000.00 руб. Новогодняя премия сотрудника Игорь Ефимов: 12000.00 руб. Оклад: 120000.00 руб. Всего к выдаче: 132000.00 руб. Новогодняя премия сотрудника Анастасия Яковлева: 20000.00 руб. Оклад: 100000.00 руб. Всего к выдаче: 120000.00 руб.
Решение:
def ny_bonus(name, last_name, salary=120000, bonus=10): print(f'Новогодняя премия сотрудника {name} {last_name}: {salary * bonus / 100:.2f} руб.\n' f'Оклад: {salary:.2f} руб.\n' f'Всего к выдаче: {salary + salary * bonus / 100:.2f} руб.\n')
Задание 5
Напишите программу, которая выводит Есть
, если в полученной от
пользователя строке есть хотя бы одно совершенное
число, равное сумме своих делителей, и Нет
в обратном случае.
Пример ввода:
5 7 8 9 34 28
Вывод:
Есть
Решение:
def perfect_number(n): sum = 0 for i in range(1, n): if n % i == 0: sum += i return sum == n numbers = list(map(int, input().split())) flag = 'Нет' for i in numbers: if perfect_number(i): flag = 'Есть' break print(flag)
Задание 6
Напишите функцию, которая принимает два позиционных
аргумента – натуральные числа n и k,
и возвращает значение биномиального
коэффициента, не используя math.factorial()
.
Пример ввода:
12 5
Вывод:
792
Решение:
def factorial(num): if num <= 1: return 1 return num * factorial(num - 1) def binomial_coeff(n, k): return int(factorial(n) / (factorial(k) * factorial(n - k))) n, k = int(input()), int(input()) print(binomial_coeff(n, k))
Задание 7
Напишите функцию, которая принимает число от 1 до 99, и возвращает его словесное описание.
Пример ввода:
25
Вывод:
двадцать пять
Решение:
def spell_number(num): ed = ['один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'] des = ['двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто'] if num < 20: return ed[num - 1] elif num >= 20: if str(num)[1] != '0': return des[int(str(num)[0]) - 2] + ' ' + ed[int(str(num)[1]) - 1] return des[int(str(num)[0]) - 2] n = int(input()) print(spell_number(n))
Задание 8
Напишите функцию, которая возвращает True
, если введенная пользователем дата
является магической, и False
в обратном случае. Магической считается дата, в которой
произведение дня и месяца равно двум последним цифрам года: 02.11.2022.
Пример ввода:
03.06.2018
Вывод:
True
Решение:
def magic_date(date): return int(date[:2]) * int(date[3:5]) == int(date[-2:]) date = input() print(magic_date(date))
Задание 9
Напишите функцию, которая принимает произвольное количество именованных аргументов, и формирует из них строку запроса. Аргументы в строке запроса должны быть отсортированы в алфавитном порядке.
Примеры вызова:
print(make_query(category='books', genre='thriller', author='Stephen_King')) print(make_query(name='Егор', last_name='Тимохин', age=25, occupation='дизайнер'
Вывод:
author=Stephen_King&category=books&genre=thriller age=25&last_name=Тимохин&name=Егор&occupation=дизайнер
Решение:
def make_query(**kwargs): return '&'.join([f'{k}={kwargs[k]}' for k in sorted(kwargs)])
Задание 10
Напишите функцию, которая принимает целое число n, и выводит на экран спиральную матрицу размера n x n, все элементы которой выровнены по левому краю.
Пример ввода:
9
Вывод:
1 2 3 4 5 6 7 8 9 32 33 34 35 36 37 38 39 10 31 56 57 58 59 60 61 40 11 30 55 72 73 74 75 62 41 12 29 54 71 80 81 76 63 42 13 28 53 70 79 78 77 64 43 14 27 52 69 68 67 66 65 44 15 26 51 50 49 48 47 46 45 16 25 24 23 22 21 20 19 18 17
Решение:
def print_matrix(n): matrix = [[0] * n for i in range(n)] vx, vy = [0, 1, 0, -1], [1, 0, -1, 0] x, y, z = 0, -1, 1 for i in range(n + n - 1): for j in range((n + n - i) // 2): x += vx[i % 4] y += vy[i % 4] matrix[x][y] = z z += 1 for i in range(len(matrix)): for j in range(len(matrix[i])): print(str(matrix[i][j]).ljust(3), end='') print() print_matrix(int(input()))
Подведем итоги
В этой статье мы научились создавать пользовательские
функции и передавать в них определенное число позиционных и именованных
аргументов, а также произвольное количество значений *args
и **kwargs
.
В следующей статье будем разбирать анонимные лямбда-функции.
Содержание самоучителя
- Особенности, сферы применения, установка, онлайн IDE
- Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
- Типы данных: преобразование и базовые операции
- Методы работы со строками
- Методы работы со списками и списковыми включениями
- Методы работы со словарями и генераторами словарей
- Методы работы с кортежами
- Методы работы со множествами
- Особенности цикла for
- Условный цикл while
- Функции с позиционными и именованными аргументами
- Анонимные функции
- Рекурсивные функции
- Функции высшего порядка, замыкания и декораторы
- Методы работы с файлами и файловой системой
- Регулярные выражения
- Основы скрапинга и парсинга
- Основы ООП: инкапсуляция и наследование
- Основы ООП – абстракция и полиморфизм
- Графический интерфейс на Tkinter
- Основы разработки игр на Pygame
- Основы работы с SQLite
- Основы веб-разработки на Flask
- Основы работы с NumPy
- Основы анализа данных с Pandas