Параметры и аргументы функции
В программировании функции могут не только возвращать данные, но также принимать их, что реализуется с помощью так называемых параметров, которые указываются в скобках в заголовке функции. Количество параметров может быть любым.
Параметры представляют собой локальные переменные, которым присваиваются значения в момент вызова функции. Конкретные значения, которые передаются в функцию при ее вызове, будем называть аргументами. Следует иметь в виду, что встречается иная терминология. Например, формальные параметры и фактические параметры. В Python же обычно все называют аргументами.
Рассмотрим схему и поясняющий ее пример:
Когда функция вызывается, то ей передаются аргументы. В примере указаны глобальные переменные num1 и num2 . Однако на самом деле передаются не эти переменные, а их значения. В данном случае числа 100 и 12. Другими словами, мы могли бы писать mathem(100, 12) . Разницы не было бы.
Когда интерпретатор переходит к функции, чтобы начать ее исполнение, он присваивает переменным-параметрам переданные в функцию значения-аргументы. В примере переменной a будет присвоено 100, b будет присвоено 12.
Изменение значений a и b в теле функции никак не скажется на значениях переменных num1 и num2 . Они останутся прежними. В Python такое поведение характерно для неизменяемых типов данных, к которым относятся, например, числа и строки. Говорят, что в функцию данные передаются по значению. Можно сказать, когда a присваивалось число 100, то это было уже другое число, не то, на которое ссылается переменная num1 . Число 100 было скопировано и помещено в отдельную ячейку памяти для переменной a .
На самом деле переменная a в момент присваивания значения может указывать на то же число 100, что и переменная num1 . Однако, когда a в результате вычислений в теле функции получает новое значение, то связывается с другой ячейкой памяти, потому что числа относятся к неизменяемым типам данных, то есть нельзя переписать значение содержащей их ячейки. При этом переменная num1 остается связанной со старым значением.
Существуют изменяемые типы данных. Для Питона, это, например, списки и словари. В этом случае данные передаются по ссылке. В функцию передается ссылка на них, а не сами данные. И эта ссылка связывается с локальной переменной. Изменения таких данных через локальную переменную обнаруживаются при обращении к ним через глобальную. Это есть следствие того, что несколько переменных ссылаются на одни и те же данные, на одну и ту же область памяти.
Необходимость передачи по ссылке связана в первую очередь с экономией памяти. Сложные типы данных, по сути представляющие собой структуры данных, обычно копировать не целесообразно. Однако, если надо, всегда можно сделать это принудительно.
Произвольное количество аргументов
Обратим внимание еще на один момент. Количество аргументов и параметров совпадает. Нельзя передать три аргумента, если функция принимает только два. Нельзя передать один аргумент, если функция требует два обязательных. В рассмотренном примере они обязательные.
Однако в Python у функций бывают параметры, которым уже присвоено значение по-умолчанию. В таком случае, при вызове можно не передавать соответствующие этим параметрам аргументы. Хотя можно и передать. Тогда значение по умолчанию заменится на переданное.
def cylinder(h, r = 1): side = 2 * 3.14 * r * h circle = 3.14 * r**2 full = side + 2 * circle return full figure1 = cylinder(4, 3) figure2 = cylinder(5) print(figure1) print(figure2)
131.88 37.68
При втором вызове cylinder() мы указываем только один аргумент. Он будет присвоен переменной-параметру h . Переменная r будет равна 1.
Согласно правилам синтаксиса Python при определении функции параметры, которым присваивается значение по-умолчанию должны следовать (находиться сзади) за параметрами, не имеющими значений по умолчанию.
А вот при вызове функции, можно явно указывать, какое значение соответствует какому параметру. В этом случае их порядок не играет роли:
… figure3 = cylinder(10, 2) figure4 = cylinder(r=2, h=10) print(figure3) print(figure4)
В данном случае оба вызова – это вызовы с одними и теми же аргументами-значениями. Просто в первом случае сопоставление параметрам-переменным идет в порядке следования. Во-втором случае – по ключам, которыми выступают имена параметров.
В Python определения и вызовы функций имеют и другие нюансы, рассмотрение которых мы пока опустим, так как они требуют более глубоких знаний, чем у нас есть на данный момент. Скажем лишь, что функции может быть определена так, что в нее можно передать хоть ни одного аргумента, хоть множество:
def few_or_many(*a): print(a) few_or_many(1) few_or_many('1', 1, 2, 'abc') few_or_many()
(1,) ('1', 1, 2, 'abc') ()
Опять же, судя по скобкам, здесь возникает упомянутый в прошлом уроке кортеж.
Практическая работа
Напишите программу, в которой определена функция int_test , имеющая один параметр. Функция проверяет, можно ли переданное ей значение преобразовать к целому числу. Если можно, возвращает логическое True . Если нельзя – False .
В основной ветке программы присвойте переменной s то, что пользователь вводит с клавиатуры. Вызовите функцию int_test() , передав ей значение s . Если функция возвращает истину, преобразуйте строку s в число n и выведите на экран значение n + 10 .
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
3. Функции¶
В программировании функцией называют именованную последовательность предложений, которая выполняет некоторые действия. Выполняемые действия описываются в определении функции.
В Python функция определяется так:
def имя(список параметров): предложения
Можно давать создаваемым функциям любые имена, нужно только помнить, что использовать ключевые слова в качестве имен нельзя. Список параметров указывает, какую информацию, если она вообще нужна, пользователь должен передать функции.
Внутри функции может быть сколько угодно предложений, причем все они должны иметь отступ вправо относительно def . В примерах в этой книге используется стандартный отступ в 4 пробела. Определение функции — это первое из нескольких составных предложений, которые мы увидим; все они строятся по такой схеме:
- Заголовок, который начинается с ключевого слова и заканчивается двоеточием.
- Тело, состоящее из одного или более предложений Python, имеющих одинаковый отступ — 4 пробела по стандарту Python — относительно заголовка.
В определении функции ключевое слово в заголовке — это def . За ним следуют имя функции и список параметров, заключенный в скобки. Список параметров может быть пустым или может содержать любое число параметров. В любом случае скобки необходимы.
Первые две функции, которые мы напишем, не имеют параметров.
def new_line(): print
Эта функция имеет имя new_line . Пустые скобки показывают, что функция не имеет параметров. Ее тело содержит единственное предложение, которое выводит символ новой строки. (Именно это происходит, когда вы используете print без аргументов.)
Определение новой функции не приводит автоматически к выполнению этой функции. Чтобы выполнить функцию, нужно сделать вызов функции. Для вызова функции записывают имя функции, за которым в скобках следует список аргументов. При вызове функции аргументы присваиваются параметрам из определения функции.
В наших первых примерах функции имеют пустой список параметров, так что вызов функции не требует аргументов. Заметьте, однако, что в вызове функции скобки необходимы:
print "First Line." new_line() print "Second Line."
Эта программа выводит:
First line. Second line.
Дополнительное пространство между двумя строками — это результат вызова функции new_line() . А что если нам понадобится больше свободного места между строками? В таком случае мы могли бы вызвать одну и ту же функцию несколько раз:
print "First Line." new_line() new_line() new_line() print "Second Line."
Или мы могли бы написать новую функцию с именем three_lines , которая выводит три символа новой строки:
def three_lines(): new_line() new_line() new_line() print "First Line." three_lines() print "Second Line."
Эта функция содержит три предложения, каждое из которых записано с отступом в 4 пробела. Поскольку следующее предложение не имеет отступа, Python понимает, что оно не является частью определения функции.
Стоит заметить несколько вещей в связи с этой программой:
- Одну и ту же функцию можно вызывать многократно. Так обычно и происходит.
- Одна функция может вызывать другую; в нашем примере three_lines вызывает new_line .
Для чего нужно утруждать себя созданием новых функций? Для этого есть много причин, и рассмотренный пример демонстрирует две из них:
- Создание функции позволяет вам дать имя группе предложений. Функции могут упростить программу, скрывая сложные вычисления за единственным вызовом функции и предлагая понятные, говорящие сами за себя, имена вместо непонятного на первый взгляд кода.
- Создание новой функции может сделать программу меньше за счет исключения повторяющегося кода. Например, короткий способ напечатать девять последовательных символов новой строки — это вызвать three_lines три раза.
Соберем вместе фрагменты кода из этого раздела в скрипт tryme1.py :
def new_line(): print def three_lines(): new_line() new_line() new_line() print "First Line." three_lines() print "Second Line."
В этой программе определяются две функции: new_line и three_lines . Составное предложение def , определяющее функцию, выполняются так же, как и другие предложения, а его результатом является создание новой функции. Предложения в теле функции не выполняются до тех пор, пока функция не будет вызвана.
Прежде чем выполнить функцию, ее нужно создать. Другими словами, определение функции должно выполняться прежде, чем в программе встречается первый вызов этой функции.
3.2. Поток выполнения¶
Чтобы быть уверенным, что функция определена прежде, чем вызывается, нужно знать порядок, в котором выполняются предложения. Порядок выполнения предложений в программе называется потоком выполнения.
Выполнение всегда начинается с первой строки программы. Предложения выполняются по одному за раз, сверху вниз.
Определения функций не нарушают поток выполнения программы, но предложения внутри функций не выполняются до тех пор, пока функция не вызвана. Хотя это нечасто используется, но можно определить одну функцию внутри другой. В этом случае, внутреннее определение не выполнится до тех пор, пока не будет вызвана внешняя функция.
Вызов функции — как объезд в потоке выполнения. Вместо того, чтобы перейти к следующему предложению, выполняется переход на первое предложение тела функции, выполняются предложения тела функции, и затем выполняется возврат туда, откуда был сделан вызов функции.
Выглядит достаточно просто, пока вы не вспомните о том, что одна функция может вызывать другую. А эта другая может вызывать третью, и так далее!
Но Python точно “знает”, откуда вызвана текущая выполняемая функция, так что каждый раз, когда функция завершается, программа продолжается с того места, где она была перед вызовом функции. Когда достигнут конец программы, она завершается.
В чем здесь мораль? Когда читаете программу, не читайте ее просто сверху вниз. Следуйте за потоком выполнения.
3.3. Параметры, аргументы и предложение import ¶
Большинству функций нужны аргументы — значения, которые используются функцией для ее работы. Например, если вы хотите найти абсолютное значение числа, то нужно указать, какого именно числа. В Python имеется встроенная функция для вычисления абсолютного значения числа:
>>> abs(5) 5 >>> abs(-5) 5
В этом примере, аргументами функции abs являются 5 и -5.
Некоторые функции принимают больше одного аргумента. Например, встроенная функция pow берет два аргумента, основание и степень. Внутри функции передаваемые в нее значения присваиваются переменным, которые называются параметры.
>>> pow(2, 3) 8 >>> pow(7, 4) 2401
Другая встроенная функция, принимающая больше одного аргумента, — функция max .
>>> max(7, 11) 11 >>> max(4, 1, 17, 2, 12) 17 >>> max(3 * 11, 5**3, 512 - 9, 1024**0) 503
В функцию max можно передать любое число аргументов, разделенных запятыми; функция вернет максимальное из переданных ей значений. Аргументами могут быть как простые значения, так и выражения. В последнем примере функция вернула 503, поскольку 503 больше, чем 33, 125 и 1.
А вот пример определенной пользователем функции с одним параметром:
def print_twice(bruce): print bruce, bruce
Эта функция принимает единственный аргумент и присваивает его значение параметру с именем bruce . Значение параметра (определяя функцию, мы понятия не имеем, какое именно это значение) выводится дважды, после чего выводится символ новой строки. Имя bruce здесь просто демонстрирует, что вы можете дать параметру какое угодно имя. Но будет правильным давать параметрам более информативные имена, чем bruce .
Интерактивный режим интерпретатора Python предоставляет удобную среду для тестирования ваших функций. Можно воспользоваться предложением import чтобы загрузить функции, определенные в скрипте, в сеанс интерпретатора.
Предположим, что функция print_twice определена в скрипте с именем chap03.py . Тогда мы сможем работать с ней в интерактивном режиме, импортировав ее в сеанс Python:
>>> from chap03 import * >>> print_twice('Spam') Spam Spam >>> print_twice(5) 5 5 >>> print_twice(3.14159) 3.14159 3.14159
При вызове функции значение аргумента присваивается соответствующему параметру из определения функции. Все выглядит так, как будто при вызове print_twice('Spam') выполняется bruce = 'Spam' , при вызове print_twice(5) выполняется bruce = 5 , а при вызове print_twice(3.14159) выполняется bruce = 3.14159 .
Значение любого типа, которое может быть напечатано, можно передать в функцию print_twice . В первом вызове функции в приведенном примере аргумент является строкой. Во втором — целым числом. А в третьем — числом с плавающей точкой.
Как и в случае со встроенными функциями, в качестве аргумента для print_twice можно использовать выражение:
>>> print_twice('Spam' * 4) SpamSpamSpamSpam SpamSpamSpamSpam
Вначале вычисляется выражение 'Spam'*4 , что дает значение 'SpamSpamSpamSpam' , а затем это значение передается в функцию print_twice как аргумент.
3.4. Композиция¶
Как и в математике, функции в Python можно комбинировать, то есть, использовать результат одной функции в качестве аргумента при вызове другой.
>>> print_twice(abs(-7)) 7 7 >>> print_twice(max(3, 1, abs(-11), 7)) 11 11
В первом случае abs(-7) дает значение 7, которое становится аргументом для print_twice . Во втором случае у нас двухуровневая композиция, так как сначала вычисляется abs(-11) , что дает 11, затем вычисление max(3, 1, 11, 7) дает 11 и, наконец, print_twice(11) отображает результат.
В качестве аргумента можно использовать переменную:
>>> michael = 'Eric, the half a bee.' >>> print_twice(michael) Eric, the half a bee. Eric, the half a bee.
Сделаем важное замечание. Имя переменной, которое мы указываем в качестве аргумента ( michael ) не имеет никакого отношения к имени параметра ( bruce ). Абсолютно все равно, с каким именем связано значение в том месте программы, откуда оно передается в функцию; внутри функции print_twice мы зовем его bruce .
3.5. Переменные и параметры являются локальными¶
Когда вы создаете локальную переменную внутри функции, она существует только внутри функции, и её невозможно использовать снаружи. Например:
def cat_twice(part1, part2): cat = part1 + part2 print_twice(cat)
Эта функция принимает два аргумента, конкатенирует их и затем дважды печатает результат. Можно вызвать эту функцию с двумя строками:
>>> chant1 = "Pie Jesu domine, " >>> chant2 = "Dona eis requiem." >>> cat_twice(chant1, chant2) Pie Jesu domine, Dona eis requiem. Pie Jesu domine, Dona eis requiem.
Когда завершается cat_twice , переменная cat уничтожается. Если попробовать вывести ее, то получим ошибку:
>>> print cat NameError: name 'cat' is not defined
Параметры также являются локальными. Например, снаружи функции print_twice не существует такой вещи, как bruce . Если попробовать её использовать, Python выдаст сообщение об ошибке.
3.6. Стековые диаграммы¶
Для того, чтобы отследить, какую переменную где можно использовать, иногда полезно нарисовать стековую диаграмму. (По-английски стек означает кипу или штабель, то есть, некоторое количество однородных предметов, положенных один на другой.) Как и диаграмма из предыдущей главы, стековые диаграммы показывают значение каждой переменной, но, кроме того, они показывают функцию, которой принадлежит каждая переменная.
Каждая функция представлена прямоугольником, возле которого записано имя функции, а внутри записаны имена ее параметров и переменных. Стековая диаграмма для предыдущего примера выглядит так:
Порядок размещения функций в стеке показывает поток выполнения. print_twice вызывается функцией cat_twice , а cat_twice вызывается из __main__ . Это специальное имя для функции самого верхнего уровня. Когда создается переменная вне каких-либо функций, она принадлежит __main__ .
Каждый параметр функции имеет то же значение, что и соответствующий ему аргумент. Так, значение part1 то же, что у chant1 , part2 — то же, что у chant2 и bruce — то же, что у cat .
Если во время выполнения функции происходит ошибка, Python печатает имя выполнявшейся функции, а также имя функции, которая ее вызвала, а также имя функции, которая вызвала эту функцию, и так далее, до функции самого верхнего уровня.
Чтобы посмотреть, как это работает, создайте скрипт Python с именем tryme2.py и следующим содержанием:
def print_twice(bruce): print bruce, bruce print cat def cat_twice(part1, part2): cat = part1 + part2 print_twice(cat) chant1 = "Pie Jesu domine, " chant2 = "Dona eis requim." cat_twice(chant1, chant2)
Мы добавили предложение print cat в функцию print_twice , но переменная cat там не определена. Выполнение этого скрипта приведет к сообщению об ошибке, похожему на это:
Traceback (innermost last): File "tryme2.py", line 11, in module> cat_twice(chant1, chant2) File "tryme2.py", line 7, in cat_twice print_twice(cat) File "tryme2.py", line 3, in print_twice print cat NameError: global name 'cat' is not defined
Этот список называется трассировкой стека. Он содержит информацию о том, в каком файле произошла ошибка, и какая строка какой функции выполнялась в это время. Он также показывает строку кода, вызвавшую ошибку.
Обратите внимание на сходство между трассировкой стека и стековой диаграммой. Это не случайное совпадение, так как в основе обеих лежит один и тот же механизм.
3.7. Глоссарий¶
Предложение, позволяющее сделать функции и переменные, определенные в скрипте Python, доступными при выполнении другого скрипта или в интерактивном режиме Python. Например, пусть имеется скрипт с именем tryme.py :
def print_thrice(thing): print thing, thing, thing n = 42 s = "And now for something completely different. "
Теперь запустим интерпретатор в той директории, где размещается tryme.py :
$ ls tryme.py $ python >>>
В tryme.py определены три имени: print_thrice , n , и s . Если попробовать использовать их, не выполнив импорт, то получим ошибку:
>>> n Traceback (most recent call last): File "", line 1, in NameError: name 'n' is not defined >>> print_thrice("ouch!") Traceback (most recent call last): File "", line 1, in NameError: name 'print_thrice' is not defined
Если, однако, импортировать всё из tryme.py , то можно будет использовать всё, что в нем определено:
>>> from tryme import * >>> n 42 >>> s 'And now for something completely different. ' >>> print_thrice("Yipee!") Yipee! Yipee! Yipee! >>>
Заметьте, что не нужно включать .py в имя скрипта в предложении import.
аргумент Значение, передаваемое функции при ее вызове. Это значение присваивается соответствующему параметру функции. вызов функции Предложение, выполняющее функцию. Оно состоит из имени функции, за которым следует список аргументов в скобках. заголовок составного предложения Первая часть составного предложения. Заголовки начинаются с ключевого слова и заканчиваются двоеточием. композиция функций Использование вызова функции в качестве аргумента при вызове другой функции. локальная переменная Переменная, определенная внутри функции. Локальная переменная может использоваться только внутри функции. определение функции Составное предложение, которое создает новую функцию, указывая ее имя, параметры и выполняемые предложения. параметр Имя, используемое внутри функции для доступа к значению, переданному в качестве аргумента. поток выполнения Порядок, в котором выполняются предложения во время выполнения программы. составное предложение
Предложение, состоящее из двух частей:
- заголовок — начинается с ключевого слова, задающего тип составного предложения, и заканчивается двоеточием.
- тело — содержит одно или более предложений, имеющих одинаковый отступ относительно заголовка.
Составное предложение строится так:
keyword expression: statement statement .
стековая диаграмма Графическое представление стека (кипы, стопки) вызываемых функций, их переменных и параметров. тело составного предложения Вторая часть составного предложения. Тело состоит из последовательности предложений, имеющих одинаковый отступ относительно заголовка. Стандартный отступ для программ на Python составляет 4 пробела. трассировка стека Список выполняющихся функций, печатаемый при возникновении ошибки выполнения. Трассировка стека перечисляет функции в порядке, в котором они вызывались. функция Именованная последовательность предложений, которая выполняет некоторые полезные действия. Функции могут иметь или не иметь параметры, могут возвращать или не возвращать результат.
3.8. Упражнения¶
- С помощью текстового редактора создайте скрипт Python с именем tryme3.py . Поместите в него функцию nine_lines , которая использует three_lines чтобы выводить девять пустых строк. Теперь добавьте функцию clear_screen , которая выводит 25 пустых строк. В последней строке вашей программы напишите вызовclear_screen .
- Переместите последнюю строку в tryme3.py в начало программы, так, чтобы вызов функцииclear_screen находился перед определением функции. Запустите программу и заметьте, какое сообщение об ошибке вы получили. Можете сформулировать правило о том, как должны располагаться в программе определения функций и вызовы функций относительно друг друга?
- Вернувшись к рабочей версии tryme3.py , поместите определение функции new_line после определения функции three_lines . Посмотрите, что произойдет, когда вы запустите эту программу. Теперь поместите определение new_line ниже вызова three_lines() . Объясните, как поведение программы иллюстрирует правило, сформулированное в предыдущем примере.
- Напишите тело в определении функцииcat_n_times так, чтобы строка s печаталась n раз:
def cat_n_times(s, n): fill in your code here>
Сохраните эту функцию в скрипте с именем import_test.py . Находясь в той директории, в которой сохранен файл (команда ls в Unix должна показать import_test.py ), запустите интерпретатор Python в интерактивном режиме и попробуйте выполнить следующее:
>>> from import_test import * >>> cat_n_times('Spam', 7) SpamSpamSpamSpamSpamSpamSpam
Параметры и аргументы функций#
Цель создания функции, как правило, заключается в том, чтобы вынести кусок кода, который выполняет определенную задачу, в отдельный объект. Это позволяет использовать этот кусок кода многократно, не создавая его заново в программе.
Как правило, функция должна выполнять какие-то действия с входящими значениями и на выходе выдавать результат.
При работе с функциями важно различать:
- параметры — это переменные, которые используются при создании функции.
- аргументы — это фактические значения (данные), которые передаются функции при вызове.
Параметры бывают обязательные и необязательные.
def f(a, b): pass
Необязательные (со значением по умолчанию):
def f(a=None): pass
В этом случае a — передавать необязательно.
Аргументы бывают позиционные и ключевые.
def summ(a, b): return a + b
summ(1, 2)
summ(a=1, b=2)
Независимо от того как параметры созданы, при вызове функции им можно передавать значения и как ключевые и как позиционные аргументы. При этом обязательные параметры надо передать в любом случае, любым способом (позиционными или ключевыми), а необязательные можно передавать, можно нет. Если передавать, то тоже любым способом.
Подробнее типы параметров и аргументов будут рассматриваться позже.
Для того, чтобы функция могла принимать входящие значения, ее нужно создать с параметрами (файл func_check_passwd.py):
In [1]: def check_passwd(username, password): . : if len(password) 8: . : print('Пароль слишком короткий') . : return False . : elif username in password: . : print('Пароль содержит имя пользователя') . : return False . : else: . : print(f'Пароль для пользователя username> прошел все проверки') . : return True . :
В данном случае, у функции два параметра: username и password.
Функция проверяет пароль и возвращает False, если проверки не прошли и True если пароль прошел проверки:
In [2]: check_passwd('nata', '12345') Пароль слишком короткий Out[2]: False In [3]: check_passwd('nata', '12345lsdkjflskfdjsnata') Пароль содержит имя пользователя Out[3]: False In [4]: check_passwd('nata', '12345lsdkjflskfdjs') Пароль для пользователя nata прошел все проверки Out[4]: True
При таком определении функции надо обязательно передать оба аргумента. Если передать только один аргумент, возникнет ошибка:
In [5]: check_passwd('nata') --------------------------------------------------------------------------- TypeError Traceback (most recent call last) ipython-input-5-e07773bb4cc8> in module> ----> 1 check_passwd('nata') TypeError: check_passwd() missing 1 required positional argument: 'password'
Аналогично, возникнет ошибка, если передать три и больше аргументов.
Функции в Python
В этой статье научимся писать собственные функции, которые являются блоками кода и предназначены для выполнения определенной задачи. Если нужно решить определенную задачу, заданную в функции, то сначала необходимо присвоить имя этой функции. Если нужно выполнять эту задачу несколько раз в программе, то не нужно вводить один и тот же код снова и снова; нужно просто вызывать эту функцию, предназначенную для обработки этой задачи. Такой вызов сообщает Python запустить код внутри функции. Так Вы обнаружите, что использование функций облегчает написание, чтение, тестирование и исправление программ.
В этой главе также узнаете, как передавать информацию в функции, узнаете, как писать определенные функции, основной задачей которых является отображение информации или других функций, предназначенных для обработки данных и возврата значений или их набора. Наконец, научитесь хранить функции в отдельных файлах, называемых модулями, чтобы упорядочить основные файлы программы.
Определение функции
Вот простая функция с названием greet_user(), которая выводит приветствие:
def greet_user(): """Display a simple greeting.""" print("Hello!") greet_user()
Этот пример демонстрирует простейшую структуру функции. Первая строка использует ключевое слово «def», чтобы сообщить Python, что вы создаёте функцию. Это определение функции сообщает Python её имя и, если применимо, что она выполняет. В скобках указывают аргументы, которые могут содержать параметры, использующиеся в функции. В этом примере имя функции — greet_user() , и ей не требуется аргументы для выполнения своей работы, поэтому в скобках ничего нет. (Но не смотря на это, скобки обязательны.) Наконец, определение функции заканчивается двоеточием.
Любые отступы, следующие за def greet_user() : составляют тело функции. Текст во второй строке представляет собой комментарий, называемый строкой документации, которая описывает, что делает функция. Такие строки заключены в тройные кавычки, которые Python ищет, когда генерирует документацию для функций в ваших программах.
Строка print(«Hello!») является единственной строкой фактического кода в теле этой функции, поэтому у greet_user() есть только одно задание — выводить «Hello!».
Когда вы хотите использовать эту функцию, вы вызываете ее. Вызов функции сообщает Python выполнить код в функции. Чтобы вызвать функцию, вы пишете имя функции, а затем любую необходимую информацию в скобках, как показано в четвертой строке. Чтобы вызвать нашу функцию, нужно ввести greet_user () . Как и ожидалось, эта функция выведет на экран слово «Hello!»:
Hello!
Передача данных в функцию
Теперь немного изменим функцию greet_user() , которая будет не только просто приветствовать пользователя, а приветствовать его по имени. Чтобы сделать это, задайте аргумент имени в скобках функции def greet_user() , таким образом вы разрешаете функции принимать значение имени пользователя. Теперь функция требует задать имя каждый раз, когда вы его её вызываете. Например передадим функции имя ‘jesse’, в скобках:
def greet_user(username): """Display a simple greeting.""" print("Hello, " + username.title() + "!") greet_user('jesse')
Когда используем так функцию: greet_user(‘jesse’) python вызывает её и передают функции информацию, необходимую для выполнения оператора print. Функция принимает переданное вами имя и отображает приветствие для этого имени:
Hello, Jesse!
Аналогично, если мы введём другое имя в функции, например: greet_user(‘sarah’) и программа выводит «Hello, Sarah!» Вы можете вызывать greet_user() столько раз, сколько захотите, и передавать любое имя, чтобы каждый раз иметь предсказуемый результат.
Аргументы и параметры
В предыдущей функции greet_user() мы задали функции значение для переменной username. Как только мы вызвали функцию и ввели данные (имя человека), функция вывела соотвествующие приветствие. Переменная username в функции greet_user() является таким образом примером параметра, части информации, которую функция должна выполнять для своей работы. Значение ‘jesse’ в greet_user (‘jesse’) является примером аргумента.
Аргумент — это часть информации, которая передается от вызова функции. Когда мы вызываем функцию, мы помещаем значение в скобках, которое мы хотим, для работоспособности функции. В этом случае аргумент ‘jesse’ был передан функции greet_user() , а значение было сохранено в параметре «username».
Примечание: Иногда говорят об аргументах и параметрах взаимозаменяемо. Не удивляйтесь, если вы увидите переменные в определении функции, которые называются аргументами, или переменные в вызове функции, которые называются параметрами. Чтобы систематизировать эту информацию приводим код, где ясно обозначается где параметр, а где его аргумент:
def my_function(paramater_1, parameter_2): print(paramater_1, parameter_2) my_function('argument_1', 'argument_2')
Передача аргументов
Так как в определении функции может быть несколько параметров, вызов этой функции должен состоять также из нескольких соответсвующих аргументов. Можно передавать аргументы функциям несколькими способами. Можно использовать позиционные аргументы, которые должны быть в том же порядке, в котором были записаны параметры; ключевые аргументы, где каждый аргумент состоит из имени переменной и значения; и списки и словари значений. Давайте посмотрим на каждый из них по очереди.
Позиционные аргументы
Когда вызывается функция, Python должен сопоставить каждый аргумент в вызове функции с параметром в её определении. Самый простой способ сделать это вводить аргументы в порядке предоставленных параметров. Такие введённые значения называются позиционными аргументами. Чтобы увидеть, как это работает, рассмотрим функцию, которая отображает информацию о домашних животных. Функция сообщает нам, каким животным является каждый питомец, и его именем, как показано здесь:
def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('hamster', 'harry')
Определение показывает, что для этой функции требуется тип животного и имя животного в первой строке кода. Когда мы вызываем description_pet () , нам нужно предоставить тип животного и его имя в указанном порядке. Например, при вызове функции аргумент ‘hamster’ сохраняется в параметре animal_type, а аргумент ‘harry’ сохраняется в параметре pet_name при использовании функции. В теле функции эти два параметра используются для отображения информации об описываемом домашнем животном. Соответственно на выходе получим результат:
I have a hamster. My hamster's name is Harry.
Многоразовый вызов функции
Можно вызывать функцию столько раз, сколько необходимо. Для описания второго, другого питомца требуется еще один вызов, функции describe_pet() :
def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('hamster', 'harry') describe_pet('dog', 'willie')
Во втором вызове функции мы передаем description_pet() аргументы «dog» и «willie». Как и в предыдущем наборе аргументов, который мы использовали, Python сопоставляет «dog» с параметром «animal_type» и «willie» с параметром pet_name . Как и прежде, функция выполняет свою работу, но на этот раз она выводит значения для собаки по имени Вилли. Теперь у нас есть хомяк по имени Гарри и собака по имени Вилли:
I have a hamster. My hamster's name is Harry. I have a dog. My dog's name is Willie.
Многократный вызов функции — очень эффективный способ программирования. Код, описывающий питомца, пишется один раз в функции. Затем в любое время, когда вы захотите описать нового питомца, вы вызываете функцию с информацией о новом питомце. Даже если бы код описания домашнего животного расширился до десяти строк, вы все равно могли бы описать нового домашнего животного всего одной строкой, снова вызвав функцию.
Можно также использовать столько аргументов в ваших функциях, сколько это требуется для решения той или иной задачи. Python работает с аргументами, которые вы указываете при вызове функции, и сопоставляет каждый из них с соответствующим параметром в определении функции.
Порядок в определении позиции аргументов
Можно получить неожиданный результат, если смешать порядок аргументов в вызове функции при использовании позиционных аргументов:
def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('harry', 'hamster')
В этом вызове функции мы вводим сначала имя, а затем и тип домашнего питомца. Поскольку в этот раз аргумент ‘harry’ указан первым, это значение сохраняется в параметре «animal_type». Аналогично, «hamster» хранится в «pet_name». Поэтому будет вот такой запутанный результат:
I have a harry. My harry's name is Hamster.
Если получается забавный результат, например как показано выше, убедитесь, что порядок аргументов в вызове функции соответствует порядку параметров в определении функции.
Ключевые слова в аргументах
Ключевым аргументом является пара имя-значение, которые передаются функции. Следует знать, что связываются имя и значение в аргументе. Аргументы ключевых слов освобождают от необходимости беспокоиться о правильном порядке аргументов в вызове функции, и они проясняют имеют свою роль для каждого значения при вызове функции. Давайте переделаем наш предыдущий код, используя ключевые аргументы, чтобы вызвать description_pet() :
def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(animal_type='hamster', pet_name='harry')
Функция describe_pet() не изменилась. Но когда вызываем функцию, мы явно сообщаем Python, с каким параметром должен сопоставляться каждый аргумент. Когда Python читает вызов функции, логика программирования знает, как сохранить аргумент «hamster» в параметре «animal_type» и аргумент «harry» в «pet_name». Порядок аргументов ключевых слов не имеет значения, потому что Python знает, куда должно идти каждое значение. В этом примере использования функции параметры введены не в том порядке, как указаны в аргументе использования функции:
describe_pet(animal_type='hamster', pet_name='harry') describe_pet(pet_name='harry', animal_type='hamster')
Не смотря на это, мы получаем совершенно правильный результат:
I have a hamster. My hamster's name is Harry. I have a hamster. My hamster's name is Harry.
Примечание: Когда вы используете ключевые аргументы, обязательно используйте точные имена параметров в определении функции.
Значения по умолчанию
При написании функции можно определять значение по умолчанию для каждого параметра. Если в вызове функции указан аргумент для параметра, Python использует значение аргумента. Если нет, он использует значение параметра по умолчанию. Поэтому, когда вы определяете значение по умолчанию для параметра, то можно исключить соответствующий аргумент, который обычно указывается в вызове функции. Использование значений по умолчанию может упростить вызовы функций и уточнить способы, которыми обычно используются функции.
Например, как Вы заметили, что большинство вызовов description_pet() используются для описания собак, вы можете установить значение по умолчанию «animal_type» в значение «dog». Теперь любой, кто вызывает description_pet() для собаки, может пропустить эту информацию:
def describe_pet(pet_name, animal_type='dog'): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(pet_name='willie')
Мы изменили определение description_pet() , чтобы включить значение по умолчанию, «dog», для «animal_type». Теперь, когда функция вызывается без указания «animal_type», Python знает, как использовать значение «dog» для этого параметра, так мы получаем соответствующий вывод:
I have a dog. My dog's name is Willie.
Обратите внимание, что порядок параметров в определении функции должен был быть изменен. Поскольку значение по умолчанию делает ненужным указание типа животного в качестве аргумента, единственным аргументом, оставшимся в вызове функции, является имя питомца. Python по-прежнему интерпретирует это как позиционный аргумент, поэтому, если функция вызывается только с именем питомца, этот аргумент будет соответствовать первому параметру, указанному в определении функции. Именно поэтому первый параметр должен быть «pet_name».
Самый простой способ использовать эту функцию сейчас — это просто указать имя собаки в вызове функции:
describe_pet('willie')
Этот вызов функции будет иметь тот же результат, что и предыдущий пример. Единственным аргументом является «willie», поэтому он соответствует первому параметру в определении «pet_name». Поскольку для «animal_type» аргумент не указан, Python использует значение по умолчанию «dog».
Чтобы описать другого питомца, можно использовать вызов функции следующим образом:
describe_pet(pet_name='harry', animal_type='hamster')
Поскольку предоставляется явный аргумент для «animal_type», Python будет игнорировать значение параметра по умолчанию.
Эквивалентные вызовы функций
Так как позиционные аргументы, ключевые аргументы и значения по умолчанию могут использоваться вместе, часто может встречаться несколько равнозначных способов вызова функции. Рассмотрим следующее определение для description_pet() с одним предоставленным значением по умолчанию:
def describe_pet(pet_name, animal_type='dog'):
В таком случае всегда должен быть указан аргумент для «pet_name», и это значение может быть предоставлено с использованием позиционного или ключевого формата. Если описываемое животное не является собакой, аргумент для «animal_type» должен быть включен в вызов, и этот аргумент также может быть указан с использованием позиционного или ключевого формата. Все следующие вызовы будут работать для этой функции:
# A dog named Willie. describe_pet('willie') describe_pet(pet_name='willie') # A hamster named Harry. describe_pet('harry', 'hamster') describe_pet(pet_name='harry', animal_type='hamster') describe_pet(animal_type='hamster', pet_name='harry')
Каждый из этих вызовов функций будет иметь тот же результат, что и в предыдущих примерах.
Примечание: Неважно, какой способ вызова вы используете. Пока ваши вызовы функций выдают желаемый результат, просто используйте способ, который легче всего понять.
Возврат значений
Возврат простого значения
Давайте посмотрим на функцию, которая принимает имя и фамилию и затем возвращает аккуратно отформатированное полное имя:
def get_formated_name(first_name, last__name): full_name = first_name + ' ' + last__name return full_name.title() musician = get_formated_name('jimi', 'hendrix') print(musician)
Функция get_formatted_name() принимает в качестве параметров имя и фамилию, как отражено в первой строке кода. Далее функция объединяет эти два параметра, добавляет пробел между ними и сохраняет результат в «full_name». Потом в переменной «full_name» преобразуем значения с использованием функции title() для отображения строки с заглавными буквами, а затем возвращаем финальное значение.
Когда вы вызываете функцию, которая возвращает значение, нужно указать переменную, в которой сохраняем возвращаемое значение. В этом случае возвращаемое значение сохраняется в переменной «musician». И в выводе данных получаем отформатированное значение полного имени:
Jimi Hendrix
Это может показаться большой работой, чтобы получить аккуратно отформатированное имя, когда мы могли бы просто написать такой код:
print("Jimi Hendrix")
Но когда создаём большую программу, которая должна хранить множество имен и фамилий отдельно, такие функции, как get_formatted_name() , становятся очень полезными. Вы сохраняете имена и фамилии отдельно, а затем вызываете эту функцию всякий раз, когда хотите отобразить полное имя.
Создание необязательного аргумента
Иногда имеет смысл делать аргумент необязательным, чтобы пользователи по их желанию предоставить дополнительную информацию. Таким образом можно использовать значения по умолчанию, чтобы сделать аргумент необязательным.
Например, скажем, мы хотим расширить нашу функцию get_formatted_name() , чтобы обрабатывать фамилию, имя и отчество:
def get_formatted_name(first_name, middle_name, last_name): """Return a full name, neatly formatted.""" full_name = first_name + ' ' + middle_name + ' ' + last_name return full_name.title() musician = get_formatted_name('john', 'lee', 'hooker') print(musician)
Эта функция работает, когда ей присваиваются имя, среднее имя и фамилия. Функция берет все три части имени и затем строит из них одну строку. Далее функция добавляет пробелы, где это необходимо, и преобразует полное имя в регистр заголовков и получаем результат:
John Lee Hooker
Но использование среднего имени не всегда необходимо, и эта функция, которая представлена выше, не будет работать, если вы попытаетесь вызвать ее только с именем и фамилией. Чтобы сделать ввод среднего имени необязательным, необходимо присвоить аргументу “middle_name“ пустое значение по умолчанию и затем игнорировать аргумент, если только пользователь не предоставит какое-либо значение. Другими словами, чтобы функция get_formatted_name() работала без среднего имени, мы устанавливаем значение “middle_name” по умолчанию пустой и переносим этот параметр в конец списка:
def get_formatted_name(first_name, last_name, middle_name=''): """Return a full name, neatly formatted.""" if middle_name: full_name = first_name + ' ' + middle_name + ' ' + last_name else: full_name = first_name + ' ' + last_name return full_name.title() musician = get_formatted_name('jimi', 'hendrix') print(musician) musician = get_formatted_name('john', 'hooker', 'lee') print(musician)
В этом примере имя построено из трех возможных частей. Поскольку всегда есть имя и фамилия, эти параметры перечислены первыми в определении функции. Параметр среднего имени является необязательным, поэтому оно указано последним в определении, а его значением по умолчанию является пустая строка.
В теле функции мы проверяем, было ли предоставлено отчество. Python интерпретирует заполненные строки строки как «True», поэтому, если «middle_name» имеет значение «True», если аргумент среднего имени находится в вызове функции, то есть указывается имя, среднее имя и фамилия, то формируется полное имя из этих аргументов. Если среднее имя не указано, пустая строка не проходит условие «if» и выполняется блок «else», то есть выводится полное имя из аргументов имени и фамилии. Вызов этой функции с именем и фамилией достаточно прост. Однако, если мы используем второе имя, мы должны убедиться, что второе имя является последним переданным аргументом, чтобы Python правильно совпал с позицией аргументов. В итоге мы получаем вот такой результат:
Jimi Hendrix John Lee Hooker
Примечание: Необязательные значения позволяют функциям обрабатывать широкий спектр вариантов использования, а вызовы функций остаются максимально простыми.
Возврат значений в словарь
Функция может возвращать любые значения, в которых вы нуждаетесь, включая более сложные структуры данных, такие как списки и словари. Например, следующая функция принимает части имени и возвращает словарь, представляющий человека:
def built_person(first_name, last_name): """Return a dictionary of information about a person.""" person = 'first': first_name, 'last': last_name> return person musician = built_person('jimi', 'hendrix') print(musician)
Функция build_person() принимает аргументы имя и фамилию и сохраняет значения в словарь. Значение «first_name» хранится с ключом «first», а значение «last_name» хранится с ключом «last». И все аргументы сохраняются в переменную «person» и далее мы используем функцию, вводим данные пользователя в отдельную переменную «musician» и выводим информацию словаря с таким результатом:
Эта функция принимает текстовую информацию и помещает ее в более значимую структуру данных, которая позволяет работать с информацией, не просто выводя ее. Строки «jimi» и «hendrix» теперь помечены как имя и фамилия. Вы можете легко расширить эту функцию, чтобы принимать дополнительные значения, такие как отчество, возраст, род занятий или любую другую информацию, которую хотите сохранить о человеке. Например, следующее изменение позволяет также сохранить возраст человека и сделать это можно в виде необязательного аргумента, как это мы уже проделывали выше:
def build_person(first_name, last_name, age=''): """Return a dictionary of information about a person.""" person = 'first': first_name, 'last': last_name> if age: person['age'] = int(age) return person musician = build_person('jimi', 'hendrix', '27') print(musician)
Мы добавляем новый необязательный параметр «age» в определение функции и присваиваем параметру пустое значение по умолчанию. Если вызов функции включает в себя значение для этого параметра, значение сохраняется в словаре. Эта функция всегда сохраняет имя человека, но также может быть изменена для хранения любой другой информации о человеке, которую вы хотите включить в программу.
Использование функции с циклом «for»
Использование функций очень широко, всё зависит от той задачи, которую Вы решаете. Например есть список пользователей и мы хотим каждого поприветствовать, т.е. вывести его отформатированным при помощи функции, сделать это можно следующим образом:
def greet_users(names): """Print a simple greeting to each user in the list.""" for name in names: msg = "Hello, " + name.title() + "!" print(msg) usernames = ['hannah', 'ty', 'margot'] greet_users(usernames)
Сначала мы задаём функцию greet_users() , в качестве аргумента мы будем использовать список пользователей. Функция перебирает получаемый список и выводит приветствие каждому пользователю. В строке «usernames» мы определяем список пользователей и затем передаем список имен пользователей в функцию greet_users() и получаем соответсвующий результат:
Hello, Hannah! Hello, Ty! Hello, Margot!
Собственно мы получили тот результат, который хотели. Каждый пользователь видит персональное приветствие, и можно вызывать эту функцию в любое время, когда хотите приветствовать определенную группу пользователей, необходимо лишь задать в переменной список пользователей.
Передача неограниченного количества аргументов
Иногда бывает необходимость принять произвольное количество аргументов. Такая необходимость возникает, когда разработчик не знает сколько данных будет передаваться. Такой случай мы разберём на ниже приведённом примере. Скажем, перед Вами встала задача создать функцию, которая подсчитывает среднее значение из неопределённого числа числовых значений. Такая функция будет выглядеть следующим образом:
def avarage_number(*numbers): return sum(numbers) / len(numbers) x = avarage_number(1, 2, 3, 24) print(x)
Обратите внимание в качестве аргументов мы ставим знак «*» — (*numbers), который указывает на то, что в качестве аргументов «numbers» может быть указанное любое количество данных, в данном случае — любое количество чисел. Далее мы возвращаем значение (функция return) из суммы введённых чисел и поделим на их количество в массиве, т.е. подсчитываем среднее значение. Затем мы создаём переменную «numbers», в которой и применяем функцию, которая подсчитывает среднее значение. В итоге выводим результат и получаем:
Вы можете вводить любое количество значений, так функция будет решать задачу, заложенную в её основу.
Использование позиционных и неограниченного количества аргументов
Во время разработки той или иной программы, приложений, может возникнуть потребность использовать позиционные аргументы совместно с аргументом, где передаётся неограниченное количество данных. Например у нас программа, которая контролирует заказ пиццы в ресторане, и один аргумент — это размер пиццы и второй аргумент — добавки, которые идут в заказе, однако какое их количество заранее никто не знает, поэтому используем метод использования неограниченного количества аргументов:
def cooking_pizza(size, *toppings): print('\nYou have ordered', size, 'sm pizza with following toppings:') for topping in toppings: print('\t-', topping) cooking_pizza(12, 'mushrooms', 'extra cheese', 'pepperoni') cooking_pizza(30, 'green paper', 'salmon')
После того, как мы объявили функцию мы передаём два аргументы (size — размер пиццы, *toppings — добавки, при этом обращаем внимание, что звёздочка даёт понять Python, что мы передаём неограниченное количество аргументов в данном параметре. Затем мы используем циклы для «toppings», чтобы перебрать все параметры и вывести их значения. И потом мы используем созданную функцию и получаем результат:
You have ordered 12 sm pizza with following toppings: - mushrooms - extra cheese - pepperoni You have ordered 30 sm pizza with following toppings: - green paper - salmon
Примечание
В этой статье мы узнали, как писать функции и передавать аргументы, чтобы они имели доступ к данным, необходимым для их полноценной работы. Мы узнали, как использовать позиционные и ключевые аргументы и как принимать произвольное количество аргументов. Привели в качестве примера функции, которые отображают вывод и функции, которые возвращают значения. Узнали, как использовать функции со списками, словарями и циклами. Одна из ваших целей как программиста должна заключаться в написании простого кода, который делает то, что вы хотите, и функции помогают сделать это. В дальнейшем Вы сами научитесь писать такие функции, которые помогут в решении определённых задач.
Стоит ещё раз отметить, что функции позволяют писать код один раз, а затем использовать его столько раз, сколько вы хотите. Когда вам нужно запустить код в функции, все, что вам нужно сделать, это написать однострочный вызов, и функция выполнит свою работу. Когда вам нужно изменить поведение функции, вам нужно изменить только один блок кода, и ваше изменение вступает в силу везде, где вы вызывали эту функцию. Использование функций облегчает чтение ваших программ. В общем использование функций — это очень полезный инструмент при программировании игр, приложений, сайтов, в дальнейшем Вы убедитесь, что они составляют большую основу создания той или иной программы. Если у Вас остались какие-либо вопросы или что-то непонятно в этой статье, то пишите свои сообщения на странице обсуждения и другие пользователи нашего сайта Вам помогут разобраться.
Другие статьи о Python
Язык программирования Python
- Операции со строкой
- Операции со списками
- Дополнительные операции со списками
- Операции со словарями
- Циклы
- Циклы со списками
- Дополнительные операции со словарями
- Ввод данных
- Условные операторы
- Циклы со словарями
- Функции
- Классы
- Работа с файлами в Python
- Тестирование кода в Python