Использование необязательных аргументов Python При Определении Функций

Оглавление

Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Определение функций Python с необязательными аргументами

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

В этом уроке вы узнаете:

  • В чем разница между параметрами и аргументами
  • Как определить функции с необязательными аргументами и значениями параметров по умолчанию
  • Как определить функции с помощью args и kwargs
  • Что делать с сообщениями об ошибках о необязательных аргументах

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

Бесплатный бонус: Нажмите здесь, чтобы получить шпаргалку по Python и изучить основы Python 3, такие как работа с типами данных, словари, списки и функции Python.

Создание функций в Python для повторного использования кода

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

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

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

В Python, по соглашению, вы должны называть функцию строчными буквами, разделяя слова символом подчеркивания, например, do_something(). Эти соглашения описаны в PEP 8, который является руководством по стилю Python. Вам нужно будет добавить круглые скобки после имени функции при ее вызове. Поскольку функции представляют собой действия, рекомендуется начинать имена функций с глагола, чтобы сделать код более читабельным.

Определение функций без входных параметров

В этом руководстве вы будете использовать пример простой программы, которая создает и поддерживает список покупок и распечатывает его когда вы будете готовы отправиться в супермаркет.

Начните с создания списка покупок:

shopping_list = {
    "Bread": 1,
    "Milk": 2,
    "Chocolate": 1,
    "Butter": 1,
    "Coffee": 1,
}


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

# optional_params.py

shopping_list = {
    "Bread": 1,
    "Milk": 2,
    "Chocolate": 1,
    "Butter": 1,
    "Coffee": 1,
}

def show_list():
    for item_name, quantity in shopping_list.items():
        print(f"{quantity}x {item_name}")

show_list()


Когда вы запустите этот скрипт, вы получите распечатку списка покупок:

$ python optional_params.py
1x Bread
2x Milk
1x Chocolate
1x Butter
1x Coffee


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

def show_list():


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

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

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

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

Определение Функций С Требуемыми Входными аргументами

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

# optional_params.py

shopping_list = {}

# ...

def add_item(item_name, quantity):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item("Bread", 1)
print(shopping_list)


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

$ python optional_params.py
{'Bread': 1}


Вы включили два параметра в сигнатуру функции:

  1. item_name
  2. quantity

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

Различие между параметрами и аргументами часто может быть упущено из виду. Это тонкое, но важное различие. Иногда вы можете найти параметры, называемые формальными параметрами, а аргументы - фактическими параметрами.

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

# optional_params.py

shopping_list = {}

def add_item(item_name, quantity):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item()
print(shopping_list)


Обратная трассировка выдаст TypeError сообщение о том, что требуются аргументы:

$ python optional_params.py
Traceback (most recent call last):
  File "optional_params.py", line 11, in <module>
    add_item()
TypeError: add_item() missing 2 required positional arguments: 'item_name' and 'quantity'


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

Использование необязательных аргументов Python Со значениями По Умолчанию

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

Значения по умолчанию, присвоенные входным параметрам

Вы можете изменить функцию add_item() таким образом, чтобы параметр quantity имел значение по умолчанию:

# optional_params.py

shopping_list = {}

def add_item(item_name, quantity=1):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item("Bread")
add_item("Milk", 2)
print(shopping_list)


В сигнатуре функции вы добавили значение по умолчанию 1 к параметру quantity. Это не означает, что значение quantity всегда будет 1. Если при вызове функции вы передадите аргумент, соответствующий quantity, то этот аргумент будет использоваться в качестве значения параметра. Однако, если вы не передадите ни одного аргумента, то будет использовано значение по умолчанию.

За параметрами со значениями по умолчанию не могут следовать обычные параметры. Подробнее о порядке определения параметров вы узнаете позже в этом руководстве.

Функция add_item() теперь имеет один обязательный параметр и один необязательный параметр. В приведенном выше примере кода вы вызываете add_item() дважды. Ваш первый вызов функции содержит единственный аргумент, который соответствует требуемому параметру item_name. В этом случае значение quantity по умолчанию равно 1. Ваш второй вызов функции имеет два аргумента, поэтому значение по умолчанию в данном случае не используется. Вы можете увидеть результат ниже:

$ python optional_params.py
{'Bread': 1, 'Milk': 2}


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

add_item(item_name="Milk", quantity=2)


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

def show_list(include_quantities=True):
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)


Теперь, когда вы используете show_list(), вы можете вызвать его без входных аргументов или передать логическое значение в качестве аргумента флага. Если вы не передаете никаких аргументов при вызове функции, то отображается список покупок с указанием названия и количества каждого товара. Функция выдаст тот же результат, если вы передадите True в качестве аргумента при вызове функции. Однако, если вы используете show_list(False), отображаются только названия элементов.

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

Общие значения аргументов по умолчанию

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

Целые числа 0 и 1 являются обычными значениями по умолчанию, которые используются, когда значение параметра должно быть целым числом. Это связано с тем, что 0 и 1 часто являются полезными резервными значениями. В функции add_item(), о которой вы писали ранее, установка количества для нового товара на 1 является наиболее логичным вариантом.

Однако, если у вас была привычка покупать по две штуки из всего, что вы покупаете в супермаркете, то, возможно, вам больше подойдет значение по умолчанию 2.

Когда входным параметром должна быть строка , обычно используется значение по умолчанию - пустая строка (""). При этом присваивается значение, тип данных которого - string, но не вводятся никакие дополнительные символы. Вы можете изменить add_item() так, чтобы оба аргумента были необязательными:

def add_item(item_name="", quantity=1):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity


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

add_item()


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

def add_item(item_name="", quantity=1):
    if not item_name:
        quantity = 0
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity


В этой версии, если в функцию не передается ни один элемент, функция устанавливает количество равным 0. Пустая строка имеет значение ложное, что означает, что bool("") возвращает False, тогда как любая другая строка будет иметь истинное значение. Когда за ключевым словом if следует истинное или ложное значение, оператор if интерпретирует их как True или False. Вы можете прочитать больше об истинных и ложных значениях в Логических значениях Python: используйте истинные значения в своем коде.

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

Еще одним распространенным значением, которое часто используется в качестве значения по умолчанию, является None. Это способ представления nothing в Python, хотя на самом деле это объект, представляющий значение null. В следующем разделе вы увидите пример того, когда None является полезным значением по умолчанию.

Типы данных, Которые Не Следует Использовать в качестве Аргументов По Умолчанию

В приведенных выше примерах в качестве значений по умолчанию использовались целые числа и строки, а None - еще одно распространенное значение по умолчанию. Это не единственные типы данных, которые вы можете использовать в качестве значений по умолчанию. Однако следует использовать не все типы данных.

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

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

def add_item(item_name, quantity, shopping_list):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list


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

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

Чтобы вызвать функцию, вам нужно присвоить данные, возвращаемые функцией, переменной:

shopping_list = add_item("Coffee", 2, shopping_list)


Вы также можете добавить параметр shopping_list к show_list(), первой функции, которую вы определили в этом руководстве. Теперь вы можете иметь в своей программе несколько списков покупок и использовать одни и те же функции для добавления товаров и отображения списков покупок:

# optional_params.py

hardware_store_list = {}
supermarket_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

hardware_store_list = add_item("Nails", 1, hardware_store_list)
hardware_store_list = add_item("Screwdriver", 1, hardware_store_list)
hardware_store_list = add_item("Glue", 3, hardware_store_list)

supermarket_list = add_item("Bread", 1, supermarket_list)
supermarket_list = add_item("Milk", 2, supermarket_list)

show_list(hardware_store_list)
show_list(supermarket_list)


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

$ python optional_params.py

1x Nails
1x Screwdriver
3x Glue

1x Bread
2x Milk


Теперь вы добавите значение по умолчанию для параметра shopping_list в add_item(), чтобы, если в функцию не передается словарь, использовался пустой словарь. Самый заманчивый вариант - сделать значением по умолчанию пустой словарь. Скоро вы поймете, почему это не очень хорошая идея, но пока вы можете попробовать этот вариант:

# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list={}):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
show_list(clothes_shop_list)


Когда вы запустите этот скрипт, вы получите приведенный ниже результат, показывающий необходимые товары из магазина одежды, что может создать впечатление, что этот код работает должным образом:

$ python optional_params.py

3x Shirt


Однако в этом коде есть серьезный недостаток, который может привести к неожиданным и неверным результатам. Вы можете добавить новый список покупок для необходимых товаров в магазине электроники, используя add_item() без аргумента, соответствующего shopping_list. Это приводит к использованию значения по умолчанию, которое, как вы надеетесь, создаст новый пустой словарь:

# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list={}):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
electronics_store_list = add_item("USB cable", 1)
show_list(clothes_shop_list)
show_list(electronics_store_list)


Вы увидите проблему, когда посмотрите на выходные данные этого кода:

$ python optional_params.py

3x Shirt
1x USB cable

3x Shirt
1x USB cable


Оба списка покупок идентичны, несмотря на то, что при каждом вызове функции вы присваивали выходные данные add_item() разным переменным. Проблема возникает из-за того, что словари являются изменяемым типом данных.

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

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

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

# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list=None):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
electronics_store_list = add_item("USB cable", 1)
show_list(clothes_shop_list)
show_list(electronics_store_list)


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

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

$ python optional_params.py

3x Shirt

1x USB cable


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

Одно из наиболее распространенных сообщений об ошибках, с которыми вы столкнетесь, - это когда вы вызываете функцию с требуемыми аргументами, но не передаете аргументы при вызове функции:

# optional_params.py

# ...

def add_item(item_name, quantity, shopping_list=None):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

add_item()


Здесь вы вызываете add_item() без передачи необходимых аргументов item_name и quantity. Вы получите TypeError всякий раз, когда отсутствует требуемый аргумент:

$ python optional_params.py
  File "optional_params.py", line 15
    add_item()
TypeError: add_item() missing 2 required positional arguments: 'item_name' and 'quantity'


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

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

Вы можете попробовать поменять порядок следования параметров со значениями по умолчанию и без них в определении add_item():

# optional_params.py

# ...

def add_item(shopping_list=None, item_name, quantity):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list


Сообщение об ошибке, которое вы получите при запуске этого кода, довольно четко объясняет правило:

$ python optional_params.py
  File "optional_params.py", line 5
    def add_item(shopping_list=None, item_name, quantity):
                                                ^
SyntaxError: non-default argument follows default argument


Параметры, не имеющие значения по умолчанию, всегда должны предшествовать параметрам, имеющим значение по умолчанию. В приведенном выше примере параметрам item_name и quantity всегда должно быть присвоено значение в качестве аргумента. Размещение параметров со значениями по умолчанию первыми сделало бы вызов функции неоднозначным. За первыми двумя обязательными аргументами может последовать необязательный третий аргумент.

Используя args и kwargs

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

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

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

Функции, принимающие любое количество аргументов

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

>>> some_items = ["Coffee", "Tea", "Cake", "Bread"]


Переменная some_items указывает на список, который, в свою очередь, содержит четыре элемента. Если вы используете some_items в качестве аргумента для print(), то вы передаете одну переменную в print():

>>> print(some_items)
['Coffee', 'Tea', 'Cake', 'Bread']


print() отображает список, как и следовало ожидать. Однако, если вам пришлось использовать *some_items в круглых скобках print(), вы получите другой результат:

>>> print(*some_items)
Coffee Tea Cake Bread


На этот раз print() отображает четыре отдельные строки, а не список. Это эквивалентно записи следующего:

>>> print("Coffee", "Tea", "Cake", "Bread")
Coffee Tea Cake Bread


Когда звездочка (*) используется непосредственно перед последовательностью, такой как some_items, она разбивается на отдельные компоненты. Когда последовательность, такая как список, распаковывается, ее элементы извлекаются и обрабатываются как отдельные объекты.

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

Теперь вы готовы определить свои собственные функции, которые принимают переменное количество входных аргументов. На данный момент вы можете упростить add_items(), указав в списке покупок только названия нужных вам товаров. Для каждого товара вы зададите количество 1. Затем вы вернетесь к включению количеств в качестве части входных аргументов в следующем разделе.

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

def add_items(shopping_list, *args):


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

# optional_params.py

shopping_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_items(shopping_list, *item_names):
    for item_name in item_names:
        shopping_list[item_name] = 1

    return shopping_list

shopping_list = add_items(shopping_list, "Coffee", "Tea", "Cake", "Bread")
show_list(shopping_list)


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

$ python optional_params.py

1x Coffee
1x Tea
1x Cake
1x Bread


Вы можете понять, что происходит с параметром item_names, посмотрев на упрощенный пример:

>>> def add_items_demo(*item_names):
...     print(type(item_names))
...     print(item_names)
...
>>> add_items_demo("Coffee", "Tea", "Cake", "Bread")
<class 'tuple'>
('Coffee', 'Tea', 'Cake', 'Bread')


При отображении типа данных можно увидеть, что item_names является кортежем. Поэтому все дополнительные аргументы присваиваются как элементы в кортеже item_names. Затем вы можете использовать этот кортеж в определении функции, как вы это делали в основном определении add_items() выше, в котором вы выполняете итерацию по кортежу item_names, используя цикл for.

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

Если вы не добавите никаких дополнительных аргументов при вызове функции, то кортеж будет пустым:

>>> add_items_demo()
<class 'tuple'>
()


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

Функции, принимающие любое количество аргументов ключевого слова

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

>>> def test_arguments(a, b):
...     print(a)
...     print(b)
...
>>> test_arguments("first argument", "second argument")
first argument
second argument
>>> test_arguments(a="first argument", b="second argument")
first argument
second argument


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

>>> test_arguments(b="second argument", a="first argument")
first argument
second argument


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

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

def add_items(shopping_list, **kwargs):


Перед именем параметра kwargs ставятся две звездочки (**). Двойная звездочка или звездочка в виде звездочки работает аналогично одиночной звездочке, которую вы использовали ранее для распаковки элементов из последовательности. Двойная звездочка используется для распаковки элементов из сопоставления. Сопоставление - это тип данных, который содержит парные значения в виде элементов, таких как словарь.

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

# optional_params.py

shopping_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_items(shopping_list, **things_to_buy):
    for item_name, quantity in things_to_buy.items():
        shopping_list[item_name] = quantity

    return shopping_list

shopping_list = add_items(shopping_list, coffee=1, tea=2, cake=1, bread=3)
show_list(shopping_list)


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

$ python optional_params.py

1x coffee
2x tea
1x cake
3x bread


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

>>> def add_items_demo(**things_to_buy):
...     print(type(things_to_buy))
...     print(things_to_buy)
...
>>> add_items_demo(coffee=1, tea=2, cake=1, bread=3)
<class 'dict'>
{'coffee': 1, 'tea': 2, 'cake': 1, 'bread': 3}


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

Заключение

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

В этом уроке вы узнали:

  • В чем разница между параметрами и аргументами
  • Как определить функции с необязательными аргументами и значениями параметров по умолчанию
  • Как определить функции с помощью args и kwargs
  • Что делать с сообщениями об ошибках о необязательных аргументах

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

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

<статус завершения article-slug="python-необязательные аргументы" class="btn-group mb-0" data-api-article-bookmark-url="/api/v1/articles/python-необязательные аргументы/bookmark/" data-api-article-завершение-status-url="/api/v1/articles/python-необязательные аргументы/завершение_статуса/"> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей о Python:%0A%0 Использование необязательных аргументов Python при определении функций" email-subject="Статья о Python для вас" twitter-text="Интересная статья о Python от @realpython:" url="https://realpython.com/python-optional-arguments /" url-title="Использование необязательных аргументов Python при Определении функций">

Смотрите сейчас, к этому уроку прилагается соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Определение функций Python с необязательными аргументами

Back to Top