Перейти к содержимому

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

  • автор:

Распаковка аргументов#

В Python выражения *args и **kwargs позволяют выполнять ещё одну задачу — распаковку аргументов.

До сих пор мы вызывали все функции вручную. И соответственно передавали все нужные аргументы.

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

Распаковка позиционных аргументов#

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

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

Еще один пример — функция config_interface (файл func_config_interface_unpacking.py):

Функция ожидает такие аргументы:

intf_name — имя интерфейса

Функция возвращает список строк для настройки интерфейса:

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

Например, список interfaces_info, в котором находятся параметры для настройки интерфейсов:

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

Ошибка вполне логичная: функция ожидает три аргумента, а ей передан 1 аргумент — список.

В такой ситуации пригодится распаковка аргументов. Достаточно добавить * перед передачей списка как аргумента, и ошибки уже не будет:

Python сам „распакует“ список info и передаст в функцию элементы списка как аргументы.

Таким же образом можно распаковывать и кортеж.

Распаковка ключевых аргументов#

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

Функция check_passwd (файл func_check_passwd_optional_param_2.py):

Список словарей username_passwd , в которых указано имя пользователя и пароль:

Если передать словарь функции check_passwd, возникнет ошибка:

Ошибка такая, так как функция восприняла словарь как один аргумент и считает что ей не хватает только аргумента password.

Если добавить ** перед передачей словаря функции, функция нормально отработает:

Python распаковывает словарь и передает его в функцию как ключевые аргументы. Запись check_passwd(**data) превращается в вызов вида check_passwd(username=’cisco’, password=’cisco’) .

Распаковка словарей в Python: лучшие методы и практики

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

Основы распаковки словарей

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

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

Здесь словарь person_dict распаковывается, и его пары ключ-значение передаются в функцию print_person() в виде именованных аргументов.

Создание словарей с использованием распаковки

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

Вот пример создания нового словаря путем распаковки существующего словаря:

Здесь новый словарь new_dict создается путем распаковки original_dict и добавления новой пары ключ-значение «c»: 3 .

Обновление словарей с использованием распаковки

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

В этом примере словарь original_dict обновляется значениями из update_dict . Поскольку оба словаря содержат ключ «b» , его исходное значение в original_dict заменяется новым значением из update_dict .

Распаковка словарей в циклах

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

Здесь мы проходим по списку словарей people_dicts , и каждый словарь распаковывается и передается в функцию print_person() в виде именованных аргументов.

Заключение

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

Распаковка аргументов для передачи в функцию Python

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

Например, встроенная range() функция ожидает отдельные аргументы start и stop . Если они не доступны отдельно, то можно распаковать аргументы из списка list или кортежа tuple , вызвав функцию с переменной этого списка/кортежа, а впереди нее поставить символ одной звездочки * :

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

Во что распаковывается словарь Python

Мы можем вызвать функцию, путем распаковки словаря d1:

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

С другой стороны можно определить новый словарь как:

Но нельзя вот так:

Так во что именно распаковываются словари? Все зависит от контекста?

Вы верно предположили — всё зависит от контекста, давайте же рассмотрим это детальнее.

Примечание: Я использую Python 3.8 для испытаний

Создание словаря с помощью литералов

Рассмотрим для того, чтобы понять отличия в других ситуациях.

Это самый привычный способ, выглядит это так:

В данном примере словарь будет создан вызовом команды BUILD_CONST_KEY_MAP, которая является специализированной версией BUILD_MAP. Описание самое обыкновенное, не будем заострять на этом внимание.

Создание словаря с помощью распаковки в литералах

Этот способ отличается от первого. Главное, что нужно понять — это не имеет никакого отношения к именованным аргументам. Это специализированный способ. Python вызовет команду BUILD_MAP_UNPACK, чтобы осуществить такое создание. Описание команды гласит:

Берёт count словарей из стека, объединяет их в один словарь, и помещает результат в стек. Осуществляет распаковку словарей в словарь вида <**x, **y, **z>.

Новое в версии 3.5.

Примечание: Вольный перевод. Sorry for my English 🙂

Распаковка в конструктор класса

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

Это похоже на BUILD_MAP_UNPACK, но используется для f(**x, **y, **z) синтаксиса вызова.

Примечание: Вольный перевод. Sorry for my English 🙂

Распаковка словаря в именованные аргументы

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

nomnoms12's user avatar

Есть несколько разных синтаксисов для создания словаря.

Вариант 1: литерал

Инициализация словаря через литерал, элементы описываются парами ключ: значение через запятую:

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

Вариант 2: конструктор

Можно создать словарь через конструктор (который можно считать обычной функцией), обращаясь к классу:

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

function(**d1) – это распаковка элементов словаря в именованные (keyword) аргументы функции. Это встроенный функционал языка для передачи позиционных и именованных аргументов извне. Например, выражение func(**<'type':'Event'>) эквивалентно func(type=’Event’) – только словарь аргументов можно ещё где-то отдельно создавать, модифицировать, передавать, что бывает крайне полезно.

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

Вариант 3: comprehension

Есть ещё comprehension синтаксис, который позволяет лаконично создавать одни итерируемые объекты из других, например:

Насчёт выражения d3 = <**d1>точно не скажу, возможно это тоже comprehension, возможно вариант литерала, а возможно отдельный синтаксис; но суть понятна, тот же dict(**d1) .

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *