# Basics_06. Функции ## Терминология на урок: **Функцией** называется отдельный блок программы. У него может быть имя, он может принимать аргументы, с которыми потом будет работать, и может возвращать результат своей работы. **Параметрами** функции называются специальныя переменные, которые будут принимать конкретные значения при вызове этой функции. Часто являются локальными переменными внутри этой функции, которые принимают аргументы в качестве значений. Альтернативное название - **формальные параметры**. **Аргументами** или **фактическими параметрами** называются переменные (выражения, литералыи пр.), переданные в функцию при вызове. По сути, аргументы - это источник реальных значений параметров функции при ее вызове. **Литерал** - фактическое значение, которое записывается в переменную или передается в функцию. К примеру, в записи `x = 1` литералом является 1. ## Функции Можно рассмотреть функцию как черный ящик, в который вкладывают параметры. Ящик что-то делает, вы можете даже не знать, что именно, а потом предоставляет вам возможность работать с результатами своей работы. ![](https://jointhejoy.ru/sites/default/files/imagecache/post_image/%D0%91%D0%B5%D0%B7%D1%8B%D0%BC%D1%8F%D0%BD%D0%BD%D1%8B%D0%B9_2.png) ### Создание, объявление функции (function declaration ) В Python функция определяется или декларируется так: ```python def say_hello(): return "Hello" res = say_hello() ``` Важнейшие элементы функции: - Ключевое слово **`def`** говорит о том, что дальше будет функция. - После **`def`** следует название функции, приведенная выше называется `say_hello`. - Затем следуют скобки с параметрами функции. - После закрывающей скобки идет двоеточие. Как мы знаем, двоеточие в Python обозначает, что далее будет некий блок кода, выделенный отступами. В случае с условием это блок условия, тело условия, в случае с циклом - тело цикла, в случае с функцией - **тело функции или код функции**. - Ключевое слово **`return`** используется в теле функции для того, чтобы завершить работу функции и вернуть ее результат. Если не написать return, функция вернет `None`. Хорошим тоном считается возвращать какое-нибудь значение явно. - Результат работы функции - результат выполнения функции, который она возвращает. В приведенном примере результатом работы функции будет строка `"Hello"`, из функции она вернется благодаря ключевому слову `return` и поместится в переменную `res`. Схематически, функцию можно изобразить следующим образом: ```python def имя_функции(): # Тело функции # Внутри тела функции прозводятся разные вычисления """ Внутри тела функции могут производиться любые действия. К примеру, условие: """ a = 10 if a < 20: return "Меньше" # возвращаемое значение elif a > 20: return "Больше" # и это возвращаемое значение else: return "Что то пошло не так..." # и это возвращаемое значение ``` В Python принято тело функции, как и тело любого блока, выделять отступом в 4 пробела. **Все, что мы обсуждаем - только лишь создание функции, но не использование ее. Для использования функции ее необходимо вызвать.** ### Вызов функции (call function) Функции создают по несольким причинам: 1. Дать имя кусочку кода. 2. Иметь возможность вызывать один и тот же кусочек кода несколько раз. 3. Абстрагироваться от реализации какого-то решения задачи, которое уже есть. 4. Объединить несколько действий в условное "одно" действие. В любом случае созданную (объявленную) функцию необходимо вызвать, чтобы она выполнила свою задачу. До тех пор, пока функция не вызвана, она бесполезна и ничего не делает. Вызовем нашу функцию **`say_hello:`** ```python say_hello() # выведет Hello ``` Синтаксис вызова функции: ```python имя_функции() # скобки обязательны при вызове функции ``` Если просто написать функцию и вызвать ее, мы не увидим возвращаемый результат. Он вернется, но после этого потеряется. Для того, чтобы этот результат не потерять, его нужно передать в работу другой функции, сохранить в переменную или любым другим образом поймать обработать. К примеру, поместим ее в функцию print в качестве аргумента: ```python print(say_hello()) # Hello ``` ### Параметры и аргументы функции Как правило, функция имеет некоторые параметры, с которыми она работает. Пример из математики, где `y` - функция от `x`: ``` y(x) = 2x y(x) = −5x + 2 y(x) = 12x2−1 ``` В Python функции так же могут принимать параметры: ```python def plus(num1, num2): result = num1 + num2 return result ``` Здесь **num1** и **num2** - параметры функции **`plus`**. #### Аргументы или парметры? **При создании функции вы описываете параметры, при вызове - передаете аргументы. Значения аргументов попадают в параметры и внутри функции - это параметры или просто локальные переменные.** В Python, если вы декларируете параметры, то вы обязаны их туда передать, иначе получите ошибку. Вызовем нашу функцию **`plus`** с двумя числами-аргументами - **10** и **5**: ```python ten = 10 five = 5 plus(ten, five) # функция вывела 15 plus(10, 5) # функция вывела 15 ``` В момент выполнения функции параметры `num1` и `num2` примут значения `10` и `5` соостветственно. Так же в python можно передавать аргументы не по порядку, но с явным указанием аргумента и соответствию аргумента передаваемому значению ```python plus(num1=10, num2=5) plus(num2=5, num1=10) ``` Как видно из примера выше, аргументы можно передавать и в переменных, и литералами. ### Виды параметров функции ```python def func(positional, keyword=value, *args, **kwargs) pass ``` В Python можно различить 4 вида параметров у функции: 1. **Позиционные аргументы** обязательны и не имеют значений по умолчанию. 2. **Аргументы с ключевым словом** необязательны и имеют значения по умолчанию. 3. **Список с произвольным количеством аргументов** необязателен и не имеет значений по умолчанию. 4. **Словарь с произвольным количеством аргументов с ключевым словом** необязателен и не имеет значений по умолчанию. ### Функция как тип данных Все в Python является объектом. Функции не выделяются и тоже являются объектами. Как и любые други типы данных, функции можно хранить в переменных, передавать параметрами в другие функции и хранить в словарях, списках и кортежах: Пример передачи функции в качестве параметра: ```python def run_operation(num1, num2, operation): return operation(num1, num2) def plus(num1, num2): return num1 + num2 def minus(num1, num2): return num1 - num2 run_operation(10, 5, plus) # 15 run_operation(10, 5, minus) # 5 ``` Хранение функции в словаре: ```python def plus(num1, num2): return num1 + num2 def minus(num1, num2): return num1 - num2 operations = { 'plus': plus, 'minus': minus } def operation(num1, num2, operations_dict, operation): return operations_dict[operation](num1, num2) ``` #### Функция Map Функция map принимает два параметра: функцию и итератор, например, список. `map` применяет к каждому элементу списка переданную функцию. ```python string_numbers = ['1', '2', '3', '4', '5'] new_list = list(map(int, string_numbers)) print(new_list) # [1, 2, 3, 4, 5, 6, 7] ``` Еще один пример: ```python def my_square(num): return num ** 2 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] squared_numbers = list(map(my_square, numbers)) print(squared_numbers) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] ``` ## Практика ###### Задание 1 Написать 2 функции. Первая функция будет принимать строку и приводить ее к нижнему регистру. Вторая функция будет принимать строку и проводить ее к верхнему регистру. После чего с помощью `map` применить ваши функции к списку строк. Отдельно каждую функцию к отдельному спику строк! ###### Задание 2 Написать функцию которая будет простое число возводить в квардрат. Необходимо возвести в квадрат все простые числа в списке используя функцию `map` ###### Задание 3 Написать собственную реализацию функции `map`. ## ДЗ ###### Уровень 1: Доделать задания по практике ###### Уровень 2: Написать функцию которая принимает список. Необходимо посчитать количество одинаковых элементов в списке. ###### Уровень 3: Самостоятельно разобраться с функцией `zip` в Python. Написать самостоятельно реализацию функции `zip`. ###### Полезные ссылки: [ZIP](https://tproger.ru/translations/implementing-zip-list-comprehensions/) [Map, Zip, Lambda](http://ninjaside.info/blog/ru/funkcii-map-i-zip-i-lambda-python/)