Функции#
Про определение функций в python можно подробно прочитать в документации по ссылке.
Объявление функции ( function definition ) состоит из заголовка и тела.
Заголовок начинается с ключевого слова def , за которым должно следовать название (имя) функции и список формальных параметров. Завершается заголовок символом двоеточия.
Далее приводится тело функции, инструкции в котором приводятся с постоянным отступом вправо относительно заголовка функции.
Первой строкой в теле функции допускается указывать документирующую строку.
Когда интерпретатор встречает определение функции, он создаёт вызываемый объект-функцию и связывает этот объект с указанным при объявлении именем. Это имя также функции сохраняется в атрибут __name__ объекта-функции.
В ячейке выше на первой строке мы объявили функцию с именем add принимающую два аргумента под именами x и y .
На следующей строке располагается документирующая строка.
Документирующая строка сохраняется в атрибут __doc__ объекта функции и также выводится в справке по функции, которую можно сгенерировать встроенной функцией help.
На последней строке функция возвращает результат вычисления выражения x + y вызывающему коду.
Управление потоком управления и возвращение значений из функции#
При вызове функции поток управления программой передаётся этой функции. Поток управления программой возвращается обратно вызывающему коду, когда исполнение функций завершается, что может произойти по трём причинам:
встречено ключевое слово return ;
достигнут конец функции;
возникло необработанное исключение, которое начало распространяться по стеку вызовов.
Последний случай разбирается позднее в разделе “ Исключения ”, разберем первые два.
Если встречается конструкция вида
т.е. ключевое слово return и некоторое выражение expression , то вызывающему коду возвращается результат вычисления expression . Именно такая ситуация и встречается в определенной выше функции add : в качестве expression выступает выражение x + y .
Если же после ключевого слова return ничего не стоит, т.е. встречается конструкция вида
то вызывающему коду возвращается значение None .
Если же функция заканчивается без ключевого слова return , то после исполнения последней инструкции тела функции вызывающему коду возвращается значение None . Т.е. следующие три определения функции эквиваленты.
Таким образом функция всегда возвращает какое-то значение, если её исполнение завершилось без возникновения исключений. Это значение явно задаётся выражением справа от ключевого слова return или возвращается None , если ключевое слово return не встретилось при исполнении тела функции или справа от оператора return ничего не указано.
Функции как объекты первого класса#
Прочитав объявление функции, интерпретатор создаёт вызываемый объект-функцию типа function и связывает его с указанным при объявлении функции именем. При этом объекты функционального типа function ничем не выделяются на фоне объектов всех остальных типов. Как и с любыми другими объектами в python можно совершать следующие операции и над функциями:
передать в качестве аргумента функции;
возвращать из функции;
В программировании такие объекты с такими свойствами принято называть объектами первого класса и далеко не во всех языках программирования функции являются таковыми. Но в python это так и давайте продемонстрируем это.
Присваивание переменной#
Присвоение переменной в python — связывание с именем. В качестве демонстрации этой возможности свяжем встроенную функцию print с именем p и вызовем её от этого имени.
Передача в качестве аргумента функции#
Передачу функции в качестве аргумента другой функции мы уже встречали на примере получения справки функцией help . Разберем пример того, как пользовательская функция может принимать в качестве параметра объект-функцию.
В ячейке выше определена примитивная функция print_function_name , которая просто печатает содержимое атрибута __name__ функции. Далее на вход этой функции сначала передаётся определенная ранее функция add . А потом на вход этой функции передаётся она сама! Да, python настолько гибкий, что функция может обработать саму себя. Правда сложно представить себе ситуацию, где такая возможность пригодится и будет лучшей из всех возможных альтернатив.
Напишем чуть более содержательную функцию apply , которая принимает на вход функцию f и список l и подменяет каждый элемент l[i] значением f(l[i]) , т.к. применяет функцию f к элементам списка l на месте.
На самом деле есть встроенная функция map, которая делает то же самое, только не на месте.
Возвращение из функции. Замыкание#
Функция может возвращать функцию из себя. Распространенное применение такого приема — декораторы (см. “ Декораторы ”). Одна из основных причин такой распространенности — возможность реализовать шаблон замыкание ( closure ).
Рассмотрим самый простой пример. Реализуем функцию, которая генерирует функцию, запоминающую момент своего создания.
Разберем, как этот пример работает. Обратим внимание на функцию make_remembering_function .
Для начала обратим внимание на то, что внутри тела этой функции объявляется другая функция remembering_function и она же возвращается в качестве результата. При каждом вызове функции make_remembering_function интерпретатор заново встречает объявление функции remembering_function , создаёт функциональный объект и связывает его с именем remembering_function в пространстве локальных имен функции make_remembering_function (каждому вызову одной и той же функции соответствует своё уникальное пространство локальных имен).
Теперь обратим внимание, что созданная функция remembering_function обращается к переменной time_of_creation , которая в этой функции не объявляется.
Такие переменные считаются свободными переменными и к списку таковых даже можно получить доступ напрямую.
Связывание свободных переменных с объектов происходит во время вызова функции. Поиск происходит в приоритете
nonlocals — пространство локальных имен замыкающей функции (в данному примере пространство локальных имен функции make_remembering_function );
globals — глобальное пространство имен модуля, в котором объявлена эта функция;
builtins — пространство встроенных имен.
Искусственно произвести процесс разрешения можно средствами модуля inspect, который предназначен для инспекции python объектов. Метод inspect.getclosurevars разрешает все имена, которые используются в функции, но не объявлены в самой функции, с объектами.
В данном примере имя time_of_creation обнаружено в пространстве имен замыкающей функции, а print в пространстве имен встроенных функций.
Рассмотрим несколько другой пример.
Этот пример работает, основываясь на тех же механизмах, что и предыдущей, так как параметры функции — локальные переменные функции. В данном примере name — локальная переменная функции make_greeter_function , и она же является переменной из локального пространства имен замыкающей функции greet (иными словами она nonlocal для функции greet ).
Опциональные и обязательные параметры функции#
Как и в C/C++ , у параметров функции могут быть значения по умолчанию ( default value ). Такие параметры ещё называют опциональными ( optional parameter ), т.к. при вызове функции их можно не указывать, а параметры без значений по умолчаний называют обязательными ( required parameter ).
В примере выше объявлена функция say_hi_n_times с обязательным параметром name и опциональным параметром n , у которого значение по умолчанию равняется 1.
Вызвать это функцию можно двумя способами:
указав оба аргумента:
указав только обязательный параметр name и опустив опциональный n :
При объявлении функции можно указывать произвольное количество как и обязательных, так и опциональных параметров, но необходимо соблюдать следующее требование: все обязательные параметры должны быть перечислены ранее всех опциональных. Т.е. допустим только следующий синтаксис.
Нарушение этого требования — синтаксическая ошибка.
Про механизм вычисления значения по умолчанию надо помнить две детали.
Во-первых, значение по умолчанию вычисляется при объявлении функции.
Здесь f() печатает строку “before”, а не “after”, потому что на момент, когда интерпретатор читал объявление функции f и создавал соответствующий объект, имя x ссылалось на объект 5 .
Во-вторых, это значение вычисляется всего один раз. Это играет роль, если значение по умолчанию — изменяемый объект.
А здесь один и тот же список разделяется между тремя вызовами функции f . Этот список создан при объявлении функции и затем используется при всех вызовах функции без второго аргумента.
Передача аргументов в функцию по имени#
Во всех предыдущих примерах аргументы передавались в функцию позиционно, т.е. то, в какой параметр попадет значение при передаче его в качестве аргумента, определялось тем, в какой позиции он был указан при вызове функции. В python можно передавать аргументы так же и по именам параметров, нарушая при этом порядок, в котором параметры перечислены в заголовке вызываемой функции.
Для этого при вызове функции указывается имя параметра, затем знак “ = ”, а затем значение, т.е. если мы хотим передать в функцию f значение value в качестве параметра с именем x , то используется следующий синтаксис.
Это сильно увеличивает количество способов передать одни и те же аргументы в функцию. Например, в случае функции с двумя параметрами существует 4 равнозначных способа её вызвать, в том числе:
передав оба аргумента позиционно;
передав первый аргумент позиционно, а второй аргумент по имени;
передав оба аргумента по имени в том же порядке, в котором они перечисленны в определении функции;
передав оба аргумента по имени в противоположном порядке, чем порядок при котором они перечислены в определении функции.
Как и в случае с опциональными параметрами в определении функции, есть ограничение на передачу параметров по имени: необходимо сначала указать все параметры, передаваемые позиционно, а только потом все параметры, передаваемые по именам.
Нарушение этого правила — синтаксическая ошибка.
Сугубо позиционные параметры и сугубо именованные параметры#
Иногда может быть удобно сделать прием каких-то параметров только по позиции, а ряда других параметров только по имени. Для этого внутри списка параметров ставятся символы “ / ” и “ * ”:
все параметры, перечисленные до символа “ / ” считаются сугубо позиционными, т.е. передавать их можно только по позиции;
все параметры, перечисленные после символа “ * ” считаются сугубо именованными, т.е. передавать их можно только по имени;
Ниже приведена иллюстрация.
Примеры некорректных вызовов функции f .
Первый два параметра должны быть переданы по позиции.
Передано 5 позиционных аргумента, а в объявлении всего 3 параметра допускающих передачу по позиции.
Перехват произвольного количества позиционных параметров.#
Python допускает синтаксис, которые позволяет перехватывать произвольное количество позиционно переданных аргументов. Для этого при объявлении функции указывается параметр с символом “ * ” перед ним. Обычно такому параметру дают имя *args (сокращение от arguments ). Ниже приведен пример такого объявления.
Вызывать такую функцию можно передавая произвольное количество параметров.
# Функции с параметрами
В программировании особе внимание уделяется концепции о локальных и глобальных переменных, а также связанное с ними представление об областях видимости. Соответственно, локальные переменные видны только в локальной области видимости, которой может выступать отдельно взятая функция. Глобальные переменные видны во всей программе. «Видны» – значит, известны, доступны. К ним можно обратиться по имени и получить связанное с ними значение.
К глобальной переменной можно обратиться из локальной области видимости. К локальной переменной нельзя обратиться из глобальной области видимости, потому что локальная переменная существует только в момент выполнения тела функции. При выходе из нее, локальные переменные исчезают. Компьютерная память, которая под них отводилась, освобождается. Когда функция будет снова вызвана, локальные переменные будут созданы заново.
Вернемся к нашей программе из прошлого урока, немного упростив ее для удобства:
Сколько здесь переменных? Какие из них являются глобальными, а какие – локальными?
Здесь пять переменных. Глобальной является только figure. Переменные a и b из функции rectangle() , а также a и h из triangle() – локальные. При этом локальные переменные с одним и тем же идентификатором a, но объявленные в разных функциях, – разные переменные.
Следует отметить, что идентификаторы rectangle и triangle , хотя и не являются именами переменных, а представляют собой имена функций, также имеют область видимости. В данном случае она глобальная, так как функции объявлены непосредственно в основной ветке программы.
В приведенной программе к глобальной области видимости относятся заголовки объявлений функций, объявление и присваивание переменной figure, конструкция условного оператора.
К локальной области относятся тела функций. Если, находясь в глобальной области видимости, мы попытаемся обратиться к локальной переменной, то возникнет ошибка. Добавьте в конце кода команду:
Однако мы можем обращаться из функций к глобальным переменным:
В данном случае из тел функций происходит обращение к имени figure, которое, из-за того, что было объявлено в глобальной области видимости, видимо во всей программе.
Наши функции не совсем идеальны. Они должны вычислять площади фигур, но выводить результат на экран им не следовало бы. Вполне вероятна ситуация, когда результат нужен для внутренних нужд программы, для каких-то дальнейших вычислений, а выводить ли его на экран – вопрос второстепенный.
Если функции не будут выводить, а только вычислять результат, то его надо где-то сохранить для дальнейшего использования. Для этого подошли бы глобальные переменные. В них можно записать результат. Напишем программу вот так:
Итак, мы ввели в программу глобальную переменную result и инициировали ее нулем. В функциях ей присваивается результат вычислений. В конце программы ее значение выводится на экран. Мы ожидаем, что программа будет прекрасно работать. Однакo:
… что-то пошло не так.
Дело в том, что в Python присвоение значения переменной совмещено с ее объявлением. (Во многих других языках это не так.) Поэтому, когда имя result впервые упоминается в локальной области видимости, и при этом происходит присваивание ей значения, то создается локальная переменная result . Это другая переменная, никак не связанная с глобальной result .
Когда функция завершает свою работу, то значение локальной result теряется, а глобальная не была изменена.
Когда мы вызывали внутри функции переменную figure, то ничего ей не присваивали. Наоборот, мы запрашивали ее значение. Интерпретатор Питона искал ее значение сначала в локальной области видимости и не находил. После этого шел в глобальную и находил.
В случае с result он ничего не ищет. Он выполняет вычисления справа от знака присваивания, создает локальную переменную result , связывает ее с полученным значением.
На самом деле можно принудительно обратиться к глобальной переменной. Для этого существует команда global :
В таком варианте программа будет работать правильно.
Однако менять значения глобальных переменных в теле функции – плохая практика. В больших программах программисту трудно отследить, где, какая функция и почему изменила их значение. Программист смотрит на исходное значение глобальной переменной и может подумать, что оно остается таким же. Сложно заметить, что какая-то функция поменяла его. Подобное ведет к логическим ошибкам.
Чтобы избавиться от необходимости использовать глобальные переменные, для функций существует возможность возврата результата своей работы в основную ветку программы. И уже это полученное из функции значение можно присвоить глобальной переменной в глобальной области видимости. Это делает программу более понятной.
Как функция принимает и возвращает данные, будет рассмотрено в следующих уроках.
# Упражнения
В языке Python можно внутри одной функции определять другую. Напишите программу по следующему описанию.
В основной ветке программы вызывается функция cylinder() , которая вычисляет площадь цилиндра. В теле cylinder() определена функция circle() , вычисляющая площадь круга по формуле πr2. В теле cylinder() у пользователя спрашивается, хочет ли он получить только площадь боковой поверхности цилиндра, которая вычисляется по формуле 2πrh, или полную площадь цилиндра. В последнем случае к площади боковой поверхности цилиндра должен добавляться удвоенный результат вычислений функции circle() .
Как вы думаете, можно ли из основной ветки программы вызвать функцию, вложенную в другую функцию? Почему?
# Возврат значений из функции. Оператор return
Функции могут передавать какие-либо данные из своих тел в основную ветку программы. Говорят, что функция возвращает значение. В большинстве языков программирования, в том числе Python, выход из функции и передача данных в то место, откуда она была вызвана, выполняется оператором return.
Если интерпретатор Питона, выполняя тело функции, встречает return, то он «забирает» значение, указанное после этой команды, и «уходит» из функции:
В данной программе в основную ветку из функции возвращается значение локальной переменной full . Не сама переменная, а ее значение, в данном случае – какое-либо число, полученное в результате вычисления площади цилиндра.
В основной ветке программы это значение присваивается глобальной переменной square. То есть выражение square = cylinder() выполняется так:
Вызывается функция cylinder() .
Из нее возвращается значение.
Это значение присваивается переменной square.
Не обязательно присваивать результат переменной, его можно сразу вывести на экран:
Здесь число, полученное из cylinder() , непосредственно передается функции print() . Если мы в программе просто напишем cylinder() , не присвоив полученные данные переменной или не передав их куда-либо дальше, то эти данные будут потеряны. Но синтаксической ошибки не будет.
В функции может быть несколько операторов return. Однако всегда выполняется только один из них. Тот, которого первым достигнет поток выполнения. Допустим, мы решили обработать исключение, возникающее на некорректный ввод. Пусть тогда в ветке except обработчика исключений происходит выход из функции без всяких вычислений и передачи значения:
Если попытаться вместо цифр ввести буквы, то сработает return, вложенный в except. Он завершит выполнение функции, так что все нижеследующие вычисления, в том числе return full, будут опущены. Пример выполнения:
Но постойте! Что это за слово None , которое нам вернул «пустой» return? Это ничего, такой объект – «ничто». Он принадлежит классу NoneType . До этого мы знали четыре типа данных, они же четыре класса: int , float , str , bool . Пришло время пятого.
Когда после return ничего не указывается, то по умолчанию считается, что там стоит объект None . Но никто вам не мешает явно написать return None .
Более того. Ранее мы рассматривали функции, которые вроде бы не возвращали никакого значения, потому что в них не было оператора return . На самом деле возвращали, просто мы не обращали на него внимание, не присваивали никакой переменной и не выводили на экран. В Python всякая функция что-либо возвращает. Если в ней нет оператора return , то она возвращает None. То же самое, как если в ней имеется «пустой» return .
# Возврат нескольких значений
В Питоне позволительно возвращать из функции несколько объектов, перечислив их через запятую после команды return :
Из функции cylinder() возвращаются два значения. Первое из них присваивается переменной sCyl, второе – fCyl. Возможность такого группового присвоения – особенность Python, обычно не характерная для других языков:
Фокус здесь в том, что перечисление значений через запятую (например, 10, 15, 19) создает объект типа tuple. На русский переводится как «кортеж». Это разновидность структур данных, которые будут изучены позже.
Когда же кортеж присваивается сразу нескольким переменным, то происходит сопоставление его элементов соответствующим в очереди переменным. Это называется распаковкой.
Таким образом, когда из функции возвращается несколько значений, на самом деле из нее возвращается один объект класса tuple. Перед возвратом эти несколько значений упаковываются в кортеж. Если же после оператора return стоит только одна переменная или объект, то ее/его тип сохраняется как есть.
Распаковка не является обязательной. Будет работать и так:
На экран выводится кортеж, о чем говорят круглые скобки. Его также можно присвоить одной переменной, а потом вывести ее значение на экран.
# Упражнения
Напишите программу, в которой вызывается функция, запрашивающая с ввода две строки и возвращающая в программу результат их конкатенации. Выведите результат на экран.
Напишите функцию, которая считывает с клавиатуры числа и перемножает их до тех пор, пока не будет введен 0. Функция должна возвращать полученное произведение. Вызовите функцию и выведите на экран результат ее работы.
# Параметры и аргументы функции
В программировании функции могут не только возвращать данные, но также принимать их, что реализуется с помощью так называемых параметров, которые указываются в скобках в заголовке функции. Количество параметров может быть любым.
Параметры представляют собой локальные переменные, которым присваиваются значения в момент вызова функции. Конкретные значения, которые передаются в функцию при ее вызове, будем называть аргументами. Следует иметь в виду, что встречается иная терминология. Например, формальные параметры и фактические параметры. В Python же обычно все называют аргументами.
Рассмотрим схему и поясняющий ее пример:
Когда функция вызывается, то ей передаются аргументы. В примере указаны глобальные переменные num1 и num2. Однако на самом деле передаются не эти переменные, а их значения. В данном случае числа 100 и 12. Другими словами, мы могли бы писать mathem(100, 12). Разницы не было бы.
Когда интерпретатор переходит к функции, чтобы начать ее исполнение, он присваивает переменным-параметрам переданные в функцию значения-аргументы. В примере переменной a будет присвоено 100, b будет присвоено 12.
Изменение значений a и b в теле функции никак не скажется на значениях переменных num1 и num2. Они останутся прежними. В Python такое поведение характерно для неизменяемых типов данных, к которым относятся, например, числа и строки. Говорят, что в функцию данные передаются по значению. Так, когда a присваивалось число 100, то это было уже другое число, не то, на которое ссылается переменная num1. Число 100 было скопировано и помещено в отдельную ячейку памяти для переменной a.
Существуют изменяемые типы данных. Для Питона, это, например, списки и словари. В этом случае данные передаются по ссылке. В функцию передается ссылка на них, а не сами данные. И эта ссылка связывается с локальной переменной. Изменения таких данных через локальную переменную обнаруживаются при обращении к ним через глобальную. Это есть следствие того, что несколько переменных ссылаются на одни и те же данные, на одну и ту же область памяти.
Необходимость передачи по ссылке связана в первую очередь с экономией памяти. Сложные типы данных, по сути представляющие собой структуры данных, обычно копировать не целесообразно. Однако, если надо, всегда можно сделать это принудительно.
# Произвольное количество аргументов
Обратим внимание еще на один момент. Количество аргументов и параметров совпадает. Нельзя передать три аргумента, если функция принимает только два. Нельзя передать один аргумент, если функция требует два обязательных. В рассмотренном примере они обязательные.
Однако в Python у функций бывают параметры, которым уже присвоено значение по-умолчанию. В таком случае, при вызове можно не передавать соответствующие этим параметрам аргументы. Хотя можно и передать. Тогда значение по умолчанию заменится на переданное:
При втором вызове cylinder() мы указываем только один аргумент. Он будет присвоен переменной-параметру h. Переменная r будет равна 1.
Согласно правилам синтаксиса Python при определении функции параметры, которым присваивается значение по-умолчанию должны следовать (находиться сзади) за параметрами, не имеющими значений по умолчанию.
А вот при вызове функции, можно явно указывать, какое значение соответствует какому параметру. В этом случае их порядок не играет роли:
… figure3 = cylinder(10, 2) figure4 = cylinder(r=2, h=10) print(figure3) print(figure4) В данном случае оба вызова – это вызовы с одними и теми же аргументами-значениями. Просто в первом случае сопоставление параметрам-переменным идет в порядке следования. Во-втором случае – по ключам, которыми выступают имена параметров.
В Python определения и вызовы функций имеют и другие нюансы, рассмотрение которых мы пока опустим, так как они требуют более глубоких знаний, чем у нас есть на данный момент. Скажем лишь, что функции может быть определена так, что в нее можно передать хоть ни одного аргумента, хоть множество:
Опять же, судя по скобкам, здесь возникает упомянутый в прошлом уроке кортеж.
# Упражнения
Напишите программу, которая:
- просит ввести число,
- проверяет возможность преобразовать введенные данные в число,
- преобразовывает значение в число и выводит число в консоль.
В программе должны быть определены следующие четыре функции:
- Функция get_input() не имеет параметров, запрашивает ввод с клавиатуры и возвращает в основную программу полученную строку.
- Функция test_input() имеет один параметр. В теле она проверяет, можно ли переданное ей значение преобразовать к целому числу. Если можно, возвращает логическое True . Если нельзя – False .
- Функция str_to_int() имеет один параметр. В теле преобразовывает переданное значение к целочисленному типу. Возвращает полученное число.
- Функция print_int() имеет один параметр. Она выводит переданное значение на экран и ничего не возвращает.
В основной ветке программы вызовите первую функцию. То, что она вернула, передайте во вторую функцию. Если вторая функция вернула True , то те же данные (из первой функции) передайте в третью функцию, а возвращенное третьей функцией значение – в четвертую.
Напишите преобразователь римских цифр (I, II, . L) в арабские (1, 2, . 50):
- в консоли просят ввести римское число;
- функция is_rim_number(num) принимает на вход число, проверяет является ли введенное значение римской цифрой и возвращает True — если является или False — если нет;
- функция rim_to_int(num) принимает на вход число, преобразует римскую цифру в целое число и возвращает полученное число.
- вывести ответ в консоль.
Напишите программу преобразования арабских целых чисел от 1 до 900 в римские.
Напишите программу преобразования римских цифр от 1 до 900 в арабские.
Напишите программу калькулятор для римских цифр, с операциями сложения и вычитания. Программа должна уметь работать с цифрами от I до L:
Параметры и аргументы функции в Python
Параметр — это значение, которое принимает функция. Аргумент — это значение, которое передается в функцию при ее вызове в программе.
Рассмотрим пример использования параметров функции в Python:
Здесь функция add_numbers() принимает два параметра: a и b . Обратите внимание на строку:
Данная строка указывает, что параметры a и b получат соответствующие значения 2 и 3 .
Параметры со значениями по умолчанию
В Python с помощью оператора = мы можем указать значения по умолчанию для параметров функции. Например:
Sum: 5
Sum: 10
Sum: 15
Обратите внимание на определение функции:
Здесь мы указали значения по умолчанию 7 и 8 для параметров a и b соответственно. Вот как работает эта программа
add_number(2, 3) — при вызове функции передаются оба значения. Следовательно, эти значения используются вместо значений по умолчанию.
add_number(2) — при вызове функции передается только одно значение. Параметру a присваивается значение 2, а для параметра b используется значение по умолчанию.
add_number() — при вызове функции значения не передаются. Следовательно, для обоих параметров a и b используются значения по умолчанию.
Именованные аргументы в Python
Именованные аргументы представляют собой пару «имя-значение», передаваемую функции. Имя и значения связываются с аргументом напрямую, так что при передаче аргумента путаница с порядком исключается. Например:
Где в функции задано значение по умолчанию python
Функция может принимать параметры. Через параметры в функцию можно передавать данные. Банальный пример — функция print() , которая с помощью параметра принимает значение, выводимое на консоль.
Теперь определим и используем свою функцию с параметрами:
Функция say_hello имеет параметр name, и при вызове функции мы можем передать этому параметру какой-либо значение. Внутри функции мы можем использовать параметр как обычную переменную, например, вывести значение этого параметра на консоль функцией print. Так, в выражении:
Строка «Tom» будет передаваться параметру name. В итоге при выполнении программы мы получим следующий консольный вывод:
При вызове функции значения передаются параметрам по позиции. Например, определим и вызовем функцию с несколькими параметрами:
Здесь функция print_person принимает два параметра: name и age. При вызове функции:
Первое значение — «Tom» передается первому параметру, то есть параметру name . Второе значение — 37 передается второму параметру — age. И внутри функции значения параметров выводятся на консоль:
Значения по умолчанию
Некоторые параметры функции мы можем сделать необязательными, указав для них значения по умолчанию при определении функции. Например:
Здесь параметр name является необязательным. И если мы не передаем при вызове функции для него значение, то применяется значение по умолчанию, то есть строка «Tom». Консольный вывод данной программы:
Если функция имеет несколько параметров, то необязательные параметры должны идти после обязательных. Например:
Здесь параметр age является необязательным и по умолчанию имеет значение 18. Перед ним расположен обязательный параметр name. Поэтому при вызове функции мы можем не передавать значение параметру age, но параметру name передать значение необходимо.
При необходимости мы можем сделать все параметры необязательными:
Передача значений параметрам по имени. Именованные параметры
В примерах выше при вызове функции значения передаются параметрами функции по позиции. Но также можно передавать значения параметрам по имени. Для этого при вызове функции указывается имя параметра и ему присваивается значение:
В данном случае значения параметрам age и name передаются по имени. И несмотря на то, что параметр name идет первым в определении функции, мы можем при вызове функции написать print_person(age = 22, name = «Tom») и таким образом передать число 22 параметру age, а строку «Tom» параметру name.
Символ * позволяет установить, какие параметры будут именнованными — то есть такие параметры, которым можно передать значения только по имени. Все параметры, которые располагаются справа от символа * , получают значения только по имени :
В данном случае параметры age и company являются именнованными.
Можно сделать все параметры именнованными, поставив перед списком параметров символ *:
Если наоборот надо определить параметры, которым можно передавать значения только по позиции, то есть позиционные параметры, то можно использовать символ / : все параметры, которые идут до символа / , являются позиционными и могут получать значения только по позиции
В данном случае параметр name является позиционным.
Для одной функции можно определять одновременно позиционные и именнованные параметры.
В данном случае параметр name располагается слева от символа /, поэтому является позиционным и обязательным — ему можно можно передать значение только по позиции.
Параметр company является именнованным, так как располагается справа от символа *. Параметр age может получать значение по имени и по позиции.
Неопределенное количество параметров
С помощью символа звездочки можно определить параметр, через который можно передавать неопределенное количество значений. Это может быть полезно, когда мы хотим, чтобы функция получала несколько значений, но мы точно не знаем, сколько именно. Например, определим функцию подсчета суммы чисел:
В данном случае функция sum принимает один параметр — *numbers , но звездочка перед названием параметра указывает, что фактически на место этого параметра мы можем передать неопределенное количество значений или набор значений. В самой функции с помощью цикла for можно пройтись по этому набору, получить каждое значение из этого набора в переменную n и произвести с ним какие-нибудь действия. Например, в данном случае вычисляется сумма переданных чисел.