Функции и получение помощи

Вы уже видели и использовали такие функции, как print и abs. Но в Python гораздо больше функций, и определение собственных функций — это большая часть программирования на Python.

В этом уроке вы узнаете больше об использовании и определении функций.

Получение помощи в python

Вы видели функцию abs в предыдущем уроке, но что делать, если вы забыли, что она делает?

Функция help(), возможно, самая важная функция Python, которую вы можете изучить. Если вы можете вспомнить, как использовать help(), вы держите ключ к пониманию большинства других функций.

Вот пример:

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.

help() отображает две вещи:

  • заголовок этой функции round(number, ndigits=None). В данном случае это говорит нам, что round() принимает аргумент, который мы можем описать как number. Кроме того, мы можем по желанию указать отдельный аргумент, который можно описать как ndigits.
  • Краткое описание на английском языке того, что делает функция.
💡
Распространенная ошибка: когда вы ищете функцию, не забудьте передать имя самой функции, а не результат вызова этой функции.

Определение функций

Встроенные функции великолепны, но мы можем продвинуться с ними лишь до определенного момента, прежде чем нам понадобится начать определять наши собственные функции. Ниже приведен простой пример.

def least_difference(a, b, c):
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    return min(diff1, diff2, diff3)

Это создает функцию с именем least_difference, которая принимает три аргумента: a, b и c.

Функции начинаются с заголовка, введенного ключевым словом def. Отступ блока кода после : запускается при вызове функции.

return — еще одно ключевое слово, уникально связанное с функциями. Когда Python встречает оператор return, он немедленно выходит из функции и передает значение с правой стороны в вызывающий контекст.

Понятно ли из исходного кода, что делает least_difference()? Если мы не уверены, мы всегда можем попробовать это на нескольких примерах:

print(
    least_difference(1, 10, 100),
    least_difference(1, 10, 10),
    least_difference(5, 6, 7), # Python позволяет использовать запятые в конце списков аргументов. Насколько это хорошо?
)

Или, может быть, функция help() может нам что-то об этом рассказать.

help(least_difference)
#Help on function least_difference in module __main__:

least_difference(a, b, c)

Python недостаточно умен, чтобы прочитать мой код и превратить его в красивое описание на английском языке. Однако, когда я пишу функцию, я могу предоставить описание в том, что называется docstring.

Строки документации (docstring)

def least_difference(a, b, c):
    """Return the smallest difference between any two numbers
    among a, b and c.
    
    >>> least_difference(1, 5, -5)
    4
    """
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    return min(diff1, diff2, diff3)

Строка документации — это строка в тройных кавычках (которая может охватывать несколько строк), которая идет сразу после заголовка функции. Когда мы вызываем help() для функции, она показывает строку документации.

help(least_difference)
#Help on function least_difference in module __main__:

least_difference(a, b, c)
    Return the smallest difference between any two numbers
    among a, b and c.
    
    >>> least_difference(1, 5, -5)
    4
💡
Примечание: последние две строки docstring — это пример вызова функции и результат. (Значок >>> — это ссылка на командную строку, используемую в интерактивных оболочках Python.) Python не запускает пример вызова — он просто нужен для удобства читателя. Соглашение о включении одного или нескольких примеров вызовов в docstring функции соблюдается далеко не повсеместно, но оно может быть очень эффективным для того, чтобы помочь кому-то понять вашу функцию. Для примера из реального мира см. эту docstring для функции numpy np.eye.

Хорошие программисты используют docstrings, если только они не собираются выбрасывать код вскоре после его использования (что случается редко). Так что вам тоже стоит начать писать docstrings!

Функции, которые не возвращают

Что произойдет, если мы не включим ключевое слово return в нашу функцию?

def least_difference(a, b, c):
    """Return the smallest difference between any two numbers
    among a, b and c.
    """
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    min(diff1, diff2, diff3)
    
print(
    least_difference(1, 10, 100),
    least_difference(1, 10, 10),
    least_difference(5, 6, 7),
)

#None None None

Python позволяет нам определять такие функции. Результатом их вызова является специальное значение None. (Это похоже на концепцию «null» в других языках.)

Без оператора return, least_difference совершенно бессмысленна, но функция с побочными эффектами может делать что-то полезное, не возвращая ничего. Мы уже видели два примера этого: print() и help() ничего не возвращают. Мы вызываем их только из-за их побочных эффектов (вывод текста на экран). Другие примеры полезных побочных эффектов включают запись в файл или изменение ввода.

mystery = print()
print(mystery) #None

Аргументы по умолчанию

Когда мы вызвали help(print), мы увидели, что функция print имеет несколько необязательных аргументов. Например, мы можем указать значение для sep, чтобы поместить некоторую специальную строку между нашими печатными аргументами:

print(1, 2, 3, sep=' < ') #1 < 2 < 3

Но если мы не укажем значение, sep будет рассматриваться как имеющий значение по умолчанию ' ' (один пробел).

print(1, 2, 3) #1 2 3

Добавление необязательных аргументов со значениями по умолчанию к определяемым нами функциям оказывается довольно простым:

def greet(who="Colin"):
    print("Hello,", who)
    
greet()
greet(who="NerdIT")
# (В этом случае нам не нужно указывать имя аргумента, поскольку оно однозначно.)
greet("world")

#Hello, Colin
#Hello, NerdIT
#Hello, world

Функции, применяемые к функциям

Вот что-то мощное, хотя поначалу может показаться очень абстрактным. Вы можете предоставлять функции в качестве аргументов другим функциям. Несколько примеров могут прояснить это:

def mult_by_five(x):
    return 5 * x

def call(fn, arg):
    """Call fn on arg"""
    return fn(arg)

def squared_call(fn, arg):
    """Call fn on the result of calling fn on arg"""
    return fn(fn(arg))

print(
    call(mult_by_five, 1),
    squared_call(mult_by_five, 1), 
    sep='\n', # '\n' is the newline character - it starts a new line
)

#5
#25

Функции, которые работают с другими функциями, называются «функциями высшего порядка». Вероятно, вы не напишете свои собственные в ближайшее время. Но в Python есть встроенные функции высшего порядка, которые вам может быть полезно вызывать.

Вот интересный пример использования функции max.

По умолчанию max возвращает наибольший из своих аргументов. Но если мы передадим функцию с помощью необязательного аргумента key, она вернет аргумент x, который максимизирует key(x) (он же 'argmax').

def mod_5(x):
    """Return the remainder of x after dividing by 5"""
    return x % 5

print(
    'Which number is biggest?',
    max(100, 51, 14),
    'Which number is the biggest modulo 5?',
    max(100, 51, 14, key=mod_5),
    sep='\n',
)

#Which number is biggest?
#100
#Which number is the biggest modulo 5?
#14