Полную лекцию (автор – И.В.Щуров) можно найти здесь. В этом файле представлены материалы занятия, кратко освещающего ключевые моменты при написании функций в предположении о том, что студентами прослушана глава Writing your own functions курса Python Data Science Toolbox (Part 1) на платформе DataCamp.
План
return
и print()
.*
.Создание функции начинается с ключевого слова (оператора) def
, за которым следует название функции и перечень аргументов функции в круглых скобках. Во избежание путаницы и конфликта имен, нежелательно давать своим функциям названия, совпадающие с названиями уже существующих в Python функций.
Хороший тон – добавлять специальную строку с описанием функции (docstring). Такая строка указывается между """
и """
и обычно содержит информацию, какие аргументы функция принимает на вход, что она с ними делает и что возвращает на выходе. Документацию к написанной функции можно увидеть, если запросить help()
в том же файле.
Строки внутри конструкции def
(после двоеточия Python автоматически добавляет отступ) называются телом функции.
Результат, который возвращает функция, указывается в строке с оператором return
. Обычно return
у функции один, в конце, но технически их может несколько (не очень хорошо с точки зрения стиля, но иногда допустимо).
Посмотрим на пример функции для вычисления модуля (абсолютного значения) числа:
my_module
;x
;m
, модуль числа x
.def my_module(x):
"""
Parameters: x is a number.
Returns an absolute value of x.
"""
if x >= 0:
m = x
else:
m = -x
return m
# посмотрим на документацию
help(my_module)
Help on function my_module in module __main__: my_module(x) Parameters: x is a number. Returns an absolute value of x.
# применим функцию
my_module(-7)
7
my_module(2.5)
2.5
А вот та же функция с двумя return
(не пришлось создавать переменную m
):
def my_module(x):
"""
Parameters: x is a number.
Returns an absolute value of x.
"""
if x >= 0:
return x
else:
return -x
Сохраним результат применения функции в res
и проверим, что все сохранилось:
res = my_module(-9)
res
9
return
и print()
¶Если в функции есть return
, она сохраняет возвращаемый результат, и к нему впоследствии можно обратиться. Если в функции нет return
, а есть только print()
, результат «молча» выводится на экран, и результат применения функции не сохраняется.
Напишем функцию my_module2()
, заменим return
на print()
и проверим, что получится.
def my_module2(x):
"""
Parameters: x is a number.
Returns an absolute value of x.
"""
if x >= 0:
m = x
else:
m = -x
print(m)
# применим функцию к -9
# результат выводится на экран
res2 = my_module2(-9)
9
res2 # но в res2 ничего не сохранилось!
# посмотрим более внимательно
# в res2 пустое значение None (так как нет return)
print(res2)
None
# с res, результатом my_module() с return,
# все хорошо
print(res)
9
Функция может принимать на вход и возвращать разные типы аргументов (число, строка, список, список списков, кортеж, словарь и так далее).
Функция может принимать на вход и возвращать несколько аргументов.
Если переменные с результатами перечислены через запятую после return
, они автоматически будут объединены в кортеж.
Напишем функцию my_power()
, которая принимает на вход два целых числа и возвращает пару чисел $a^b$ и $b^a$.
def my_power(a, b):
return a**b, b**a
# применяем и видим кортеж (tuple) из двух чисел
my_power(7, 2)
(49, 128)
*
¶Если мы хотим, чтобы функция умела работать с произвольным набором аргументов (например, набор чисел любой длины, перечисленных через запятую), можем воспользоваться оператором *
, который добавит вокруг перечисленных аргументов круглые скобки, то есть объединит все в кортеж.
Пример с использованием *
: функция my_sum()
, которая принимает на вход сколько угодно чисел (nums
, могли подставить сюда любое название) и считает их сумму.
def my_sum(*nums):
return sum(nums)
my_sum(2, 7, 8, 1, 0) # просто перечисляем числа через запятую
18
Еще пример с использованием *
: функция my_text()
, которая принимает на вход любое количество слов, а затем склеивает их в одну строку:
def my_text(*words):
return " ".join(words)
my_text("one", "two", "three")
'one two three'
При создании функции можно задать значения аргументов по умолчанию – значения аргументов, которые будут использоваться, если пользователь забыл их указать. Многие функции Python имеют значения аргументов по умолчанию.
Пример 1. Если в функции round()
мы пишем только одно число, Python округляет это число до целого (использует значение аргумента по умолчанию, ndigits=None
).
round(7.3) # округляет до целого
7
# смотрим в документации на аргументы
help(round)
Help on built-in function round in module builtins: round(number, ndigits=None) Round a number to a given precision in decimal digits. The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as the number. ndigits may be negative.
Пример 2. Если в функции print()
мы указываем только объекты, которые нужно вывести на экран, Python использует значения аргументов разделитель (sep
) и конец строки (end
) по умолчанию: в качестве разделителя используется пробел, а на конце строки добавляется переход на новую строку.
print("a", "b", "c")
a b c
help(print)
Help on built-in function print in module builtins: print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: file: a file-like object (stream); defaults to the current sys.stdout. sep: string inserted between values, default a space. end: string appended after the last value, default a newline. flush: whether to forcibly flush the stream.
В своей функции тоже можно задать значение аргумента по умолчанию. Напишем простую функцию hello()
, которая будет приветствовать пользователя на разных языках.
def hello(name, lang):
if lang == "ru":
print("Привет,", name)
if lang == "en":
print("Hello,", name)
if lang == "fr":
print("Bonjours,", name)
# все хорошо
hello("Alla", "en")
Hello, Alla
# забыли второй аргумент – ошибка
hello("Alla")
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-26-8236f633aa04> in <module> 1 # забыли второй аргумент – ошибка ----> 2 hello("Alla") TypeError: hello() missing 1 required positional argument: 'lang'
Поправим: в качестве языка по умолчанию выставим русский. Теперь, если при вызове функции мы забудем указать язык, программа не выдаст ошибку, а автоматически выберет русский:
def hello(name, lang="ru"):
if lang == "ru":
print("Привет,", name)
if lang == "en":
print("Hello,", name)
if lang == "fr":
print("Bonjours,", name)
hello("Alla")
Привет, Alla
Если пользователь укажет другой язык, естественно, функция будет приветствовать его на нем:
hello("Alla", "en")
Hello, Alla
Важное дополнение: аргументы со значениями по умолчанию всегда записываются в def
после «обязательных» аргументов. Если записать их в другом порядке, получим ошибку синтаксиса:
def hello(lang="ru", name):
if lang == "ru":
print("Привет,", name)
if lang == "en":
print("Hello,", name)
if lang == "fr":
print("Bonjours,", name)
File "<ipython-input-30-b11b01f2edee>", line 1 def hello(lang="ru", name): ^ SyntaxError: non-default argument follows default argument
Вообще для функций порядок аргументов важен, если мы указываем их без названия. Если мы знаем, что на первом месте в hello()
должно стоять имя, а на втором – язык, это нужно учитывать при использовании функции. Если мы поменяем их местами, мы либо получим ошибку, либо функция не сработает, как нужно:
# ничего не печатает, так как функция понимает, что
# Alla – это язык, кода для такого условия не находит
hello("en", "Alla")
Но, если названия аргументов записывать явно, порядок уже не важен:
hello(lang="fr", name="Alla")
Bonjours, Alla