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

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

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

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

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

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

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

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

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

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

# 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 может быть более подходящей для вас.

Когда входным параметром должна быть строка, обычно используется значение по умолчанию пустая строка (""). Это присваивает значение, тип данных которого является строковым, но не вводит никаких дополнительных символов. Вы можете изменить 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. Это способ Python ничего не представлять, хотя на самом деле это объект, представляющий нулевое значение. Вы увидите пример того, когда None является полезным значением по умолчанию для использования в следующем разделе.

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

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

В этом разделе вы увидите, почему изменяемые типы данных не следует использовать в качестве значений по умолчанию в определениях функций. Изменяемый объект-это объект, значения которого могут быть изменены, например, список или словарь. Вы можете узнать больше о изменяемых и неизменяемых типах данных в разделе Неизменяемость в 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 in 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 в качестве аргумента to 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

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

>>> 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 на новый уровень.