Функции в Python

Материал из Викижурнал
Функции в Python
Функции в Python
Функции в 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" и выводим информацию словаря с таким результатом:

 {'first': 'jimi', 'last': 'hendrix'}

Эта функция принимает текстовую информацию и помещает ее в более значимую структуру данных, которая позволяет работать с информацией, не просто выводя ее. Строки "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", в которой и применяем функцию, которая подсчитывает среднее значение. В итоге выводим результат и получаем:

7.5

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

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

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

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