Уроки технологии
Технология Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Функции

Следующий шаг после использования процедурного кода — написать модульное программное обеспечение с помощью функций. Функции, от самых простых до функций с несколькими аргументами, позволяют создать код, который можно использовать повторно. Цели обучения

К концу этого модуля вы сможете:

Использовать функции с различными типами возвращаемых значений.
Использовать многоразовый код путем обособления общих шаблонов в отдельные функции.

Сценарий: упорядочивание данных о космическом корабле

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

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

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

Чем меньше в программе повторений и больших функций, тем проще ее читать и обслуживать. Ее также проще отлаживать, если что-то пошло не так.

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

Важно!

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

Функции без аргументов

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

def rocket_parts():
    print("payload, propellant, structure")

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

>>> rocket_parts()
'payload, propellant, structure'

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

>>> output = rocket_parts()
payload, propellant, structure
>>> output is None
True

Возможно, вас удивит, что значение переменной output — None. Это вызвано тем, что функция rocket_parts() не возвратила значение явным образом. В Python, если функция не возвращает значение явным образом, она неявно возвращает None. Если изменить функцию, чтобы она возвращала стоку, у переменной output будет другое значение:

>>> def rocket_parts():
...     return "payload, propellant, structure"
...
>>> output = rocket_parts()
>>> output
'payload, propellant, structure'

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

Не нужно всегда назначать возврат функции. В большинстве случаев, когда функция не возвращает значение (или значения) явно, это означает, что вам не нужно назначать или использовать неявное возвращаемое значение None.

Обязательные и необязательные аргументы

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

Пример встроенной функции с обязательным аргументом — any(). Эта функция принимает итерируемый объект (например, список) и возвращает значение True, если какой-либо элемент в итерируемом объекте имеет значение True. В противном случае она возвращает False.

>>> any([True, False, False])
True
>>> any([False, False, False])
False

При вызове any() без аргументов возникает исключение с дополнительной информацией. В сообщении об ошибке объясняется, что необходим по крайней мере один аргумент:

>>> any()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: any() takes exactly one argument (0 given)

Можно убедиться, что некоторые функции допускают необязательные аргументы, используя другую встроенную функцию с именем str(). Эта функция создает строку из аргумента. Если аргумент не передается, возвращается пустая строка:

>>> str()
''
>>> str(15)
'15'

Использование аргументов функции

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

Обязательный аргумент

Например, на космическом корабле функцию без обязательных входных данных можно сравнить с компьютером, у которого есть кнопка, чтобы узнать текущее время. При нажатии кнопки компьютерный голос скажет время. Обязательные входные данные можно сравнить с местом назначения, которое требуется для вычисления расстояния поездок. Обязательные входные данные называются аргументами функции.

Чтобы указать аргумент, вставьте его в круглые скобки:

def distance_from_earth(destination):
    if destination == "Moon":
        return "238,855"
    else:
        return "Unable to compute to that destination"

Попробуйте вызвать функцию distance_from_earth() без аргументов:


>>> distance_from_earth()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: distance_from_earth() missing 1 required positional argument: 'destination'

Python выдает TypeError с сообщением об ошибке, где говорится, что функции требуется аргумент с именем destination. Если компьютеру на космическом корабле нужно рассчитать расстояние до конечного пункта, необходимо обязательно указать пункт назначения. В примере кода есть два пути для ответа: один для Луны, а другой — для другого объекта. Укажите Луну в качестве входных данных, чтобы получить ответ:

>>> distance_from_earth("Moon")
'238,855'

Так как имеется условие catch-all, попробуйте использовать любую другую строку в качестве пункта назначения, чтобы проверить это поведение:

>>> distance_from_earth("Saturn")
'Unable to compute to that destination'

Несколько обязательных аргументов

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


def days_to_complete(distance, speed):
    hours = distance/speed
    return hours/24

Теперь используйте расстояние от Земли до Луны, чтобы вычислить, сколько дней будет длиться полет до Луны на постоянной скорости 75 миль в час:

>>> days_to_complete(238855, 75)
132.69722222222222

Функции в качестве аргументов

Вы можете использовать значение функции days_to_complete() и присвоить его переменной, а затем передать ее round() (встроенная функция, округляющая до ближайшего целого числа), чтобы получить целое число:

>>> total_days = days_to_complete(238855, 75)
>>> round(total_days)
133

Использование аргументов ключевых слов

Необязательным аргументам необходимо присвоить значение по умолчанию. Эти именованные аргументы называются аргументами ключевого слова. Значения аргументов ключевого слова должны быть определены в самих функциях. При вызове функции, которая определена с аргументами ключевого слова, их не обязательно использовать.

“Аполлону-11” потребовалось около 51 часа, чтобы достичь Луны. Давайте создадим функцию, которая возвращает предполагаемое время прибытия, используя то же значение, что и для “Аполлона-11”:

from datetime import timedelta, datetime

def arrival_time(hours=51):
    now = datetime.now()
    arrival = now + timedelta(hours=hours)
    return arrival.strftime("Arrival: %A %H:%M")

Функция использует модуль datetime для определения текущего времени. Она использует timedelta, чтобы разрешить операцию сложения, которая приводит к новому объекту времени. После вычисления результата возвращается приблизительное значение arrival, отформатированное как строка. Попробуйте вызвать ее без аргументов:

>>> arrival_time()
'Arrival: Saturday 16:42'

Несмотря на то, что функция определяет аргумент ключевого слова, она позволяет не передавать его при вызове функции. В этом случае переменной hours по умолчанию присвоено значение 51. Чтобы проверить правильность текущей даты, используйте 0 в качестве значения для hours:

>>> arrival_time(hours=0)
'Arrival: Thursday 13:42'

Комбинация аргументов и аргументов ключевого слова

Иногда функции требуется сочетание аргументов и аргументов ключевого слова. В Python это сочетание должно иметь определенный порядок. Аргументы всегда объявляются первыми, за ними следуют аргументы ключевого слова.

Измените функцию arrival_time(), чтобы получить обязательный аргумент, который является именем пункта назначения:

from datetime import timedelta, datetime

def arrival_time(destination, hours=51):
    now = datetime.now()
    arrival = now + timedelta(hours=hours)
    return arrival.strftime(f"{destination} Arrival: %A %H:%M")

Так как был добавлен обязательный аргумент, вызывать функцию без аргументов уже нельзя:

>>> arrival_time()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: arrival_time() missing 1 required positional argument: 'destination'

Чтобы избежать этой ошибки, используйте “Moon” в качестве значения для destination:

>>> arrival_time("Moon")
'Moon Arrival: Saturday 16:54'

Вы также можете передать более двух значений, но их необходимо разделить запятыми. Для перехода на орбиту потребуется около 8 минут (0,13 часов), так что используйте это значение в качестве аргумента:

>>> arrival_time("Orbit", hours=0.13)
'Orbit Arrival: Thursday 14:11'

Использование переменных аргументов

В Python можно использовать любое количество аргументов и аргументов ключевого слова без объявления каждого из них. Это удобно, если функция может получить неизвестное число входных данных.

Переменные аргументы

Аргументы в функциях являются обязательными. Но если вы используете переменные аргументы, функция позволяет передавать любое количество аргументов (включая 0). Для обозначения переменных аргументов используется префикс в виде одной звездочки (*) перед именем аргумента.

Следующая функция выводит полученные аргументы:

def variable_length(*args):
    print(args)

Примечание

Вызывать args переменных аргументов не обязательно. Можно использовать любое допустимое имя переменной. Хотя *args и *a часто встречаются, лучше использовать одинаковое соглашение во всем проекте.

В этом случае *args указывает функции принимать любое количество аргументов (включая 0). В функции теперь доступно args в качестве переменной, содержащей все аргументы в виде кортежа. Попробуйте выполнить функцию, передав любое число или тип аргументов:

>>> variable_length()
()
>>> variable_length("one", "two")
('one', 'two')
>>> variable_length(None)
(None,)

Как видите, не существует ограничений на число или тип передаваемых аргументов.

Перед запуском космический корабль проходит несколько этапов. В зависимости от задач или задержек выполнение этих этапов может занять больше времени, чем запланировано. Давайте создадим функцию переменной длины, которая может вычислить количество минут до запуска, учитывая длительность каждого этапа:

def sequence_time(*args):
    total_minutes = sum(args)
    if total_minutes < 60:
        return f"Total time to launch is {total_minutes} minutes"
    else:
        return f"Total time to launch is {total_minutes/60} hours"

Попробуйте выполнить функцию, передав любое количество минут:


>>> sequence_time(4, 14, 18)
'Total time to launch is 36 minutes' 
>>> sequence_time(4, 14, 48)
'Total time to launch is 1.1 hours'

Примечание

При использовании переменных аргументов каждому значению больше не присваивается имя переменной. Все значения теперь являются частью имени переменной catch-all, в которой используется звездочка (args в этих примерах).

Переменные аргументы ключевого слова

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

def variable_length(**kwargs):
    print(kwargs)

Попробуйте пример функции, которая выводит имена и значения, переданные в виде kwargs:


>>> variable_length(tanks=1, day="Wednesday", pilots=3)
{'tanks': 1, 'day': 'Wednesday', 'pilots': 3}

Если вы уже знакомы со словарями Python, вы заметите, что аргументы ключевого слова переменной длины присваиваются в виде словаря. Для взаимодействия с переменными и значениями используйте те же операции, что и для словаря.

Примечание

Как и в случае с переменными аргументами, вам необязательно использовать kwargs при использовании переменных аргументов ключевого слова. Можно использовать любое допустимое имя переменной. Хотя **kwargs и **kw часто встречаются, лучше использовать одинаковое соглашение во всем проекте.

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

def crew_members(**kwargs):
    print(f"{len(kwargs)} astronauts assigned for this mission:")
    for title, name in kwargs.items():
        print(f"{title}: {name}")

Попробуйте эту функцию на экипаже “Аполлона-11”:


>>> crew_members(captain="Neil Armstrong", pilot="Buzz Aldrin", command_pilot="Michael Collins")
3 astronauts assigned for this mission:
captain: Neil Armstrong
pilot: Buzz Aldrin
command_pilot: Michael Collins

Так как вы можете передать любое сочетание аргументов ключевого слова, избегайте повторяющихся ключевых слов. Повторение ключевых слов приведет к ошибке: Python

>>> crew_members(captain="Neil Armstrong", pilot="Buzz Aldrin", pilot="Michael Collins")
  File "<stdin>", line 1
SyntaxError: keyword argument repeated: pilot

Общие принципы функций:

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