Справочник по Python · модуль 6 · функции и модули
Глава 6.6
Распаковка
аргументов * и **
При вызове функции * превращает итерируемый объект в отдельные позиционные аргументы, а ** — отображение в именованные. Похожие записи объединяют коллекции и разделяют последовательность между переменными.
- Категория
- Вызов функций
- Уровень
- Средний
- Связанные темы
- Аргументы, списки, кортежи, словари
- Зачем это знать
- Передавать готовые коллекции и собирать новые
§1Одинаковые символы — два направления
| Где запись | * | ** |
|---|---|---|
в параметрах def | собирает позиционные аргументы в кортеж | собирает именованные аргументы в словарь |
| в вызове функции | раскладывает итерируемый объект по позициям | раскладывает отображение по именам |
§2Звёздочка при вызове функции
def add(a, b, c): return a + b + c numbers = [1, 2, 3] print(add(*numbers))
6
Работают список, кортеж, range и другие итерируемые объекты. Количество полученных значений должно подходить сигнатуре функции.
§3Две звёздочки при вызове
Ключи отображения становятся именами аргументов, значения — передаваемыми данными. Для обычной функции ключи должны быть строками и совпадать с допустимыми именами параметров.
def greet(name, age): print(name, age) person = {"name": "Алиса", "age": 30} greet(**person)
Алиса 30
§4* и ** в одном вызове
Сначала передаются позиционные аргументы, затем именованные. Один параметр не должен получить значение дважды.
def show(a, b, c, name): print(a, b, c, name) numbers = [1, 2, 3] profile = {"name": "Макс"} show(*numbers, **profile)
1 2 3 Макс
§5Несколько распаковок в вызове
def show(a, b, c, d): print(a, b, c, d) left = [1, 2] right = (3, 4) show(*left, *right)
1 2 3 4
§6Распаковка внутри списка
Звёздочка добавляет в новый список каждый элемент указанного итерируемого объекта.
left = [1, 2, 3] right = [4, 5, 6] numbers = [*left, 0, *right] print(numbers)
[1, 2, 3, 0, 4, 5, 6]
§7Распаковка внутри словаря
Две звёздочки копируют пары «ключ — значение». Если ключ повторяется, более позднее значение заменяет предыдущее.
defaults = {"theme": "light", "size": 14}
user = {"theme": "dark"}
settings = {**defaults, **user}
print(settings){'theme': 'dark', 'size': 14}§8Распаковка при присваивании
Количество имён должно совпадать с количеством значений.
red, green, blue = [255, 128, 0] print(red, green, blue)
255 128 0
§9Звёздочка собирает остаток
В присваивании только одно имя может иметь звёздочку. Оно получает список из всех значений, не распределённых между остальными именами.
first, *middle, last = [1, 2, 3, 4, 5] print(first) print(middle) print(last)
1 [2, 3, 4] 5
§10Автоматическая распаковка в цикле
Цикл может сразу разделить каждый элемент на несколько имён. Звёздочка не нужна, если число частей известно.
pairs = [("x", 10), ("y", 20)] for name, value in pairs: print(name, value)
x 10 y 20
§11Частые ошибки
| Что написано | Что произойдёт | Как правильно |
|---|---|---|
add(numbers) при трёх параметрах | функция получает один список вместо трёх чисел | add(*numbers) |
greet(person) при параметрах name, age | словарь передаётся одним позиционным аргументом | greet(**person) |
| ключ словаря не совпадает с параметром | TypeError о неожиданном именованном аргументе | согласовать ключи с сигнатурой или принять **kwargs |
a, b = [1, 2, 3] | ValueError: слишком много значений | a, *rest = [1, 2, 3] |
a, *left, *right = values | SyntaxError: две звёздочки в одном присваивании | использовать только одну переменную для остатка |
§12Проверьте себя
Что делает *items в вызове функции?
Передаёт каждый элемент итерируемого объекта как отдельный позиционный аргумент.
Что требуется от словаря в function(**data)?
Его ключи должны быть строками и подходить именам параметров функции, если она не принимает произвольные **kwargs.
Какой тип получает имя со звёздочкой при присваивании?
Список со всеми оставшимися элементами.
§13Шпаргалка
function(*items)function(**data)[*left, *right]first, *rest = itemsИтог главы
В вызове функции * распаковывает итерируемый объект в позиционные аргументы, а ** — отображение в именованные. В литералах эти символы объединяют коллекции, а звёздочка в присваивании собирает оставшиеся элементы в список.