Модуль 6 · Функции и модули

Справочник по Python · модуль 6 · функции и модули

Глава 6.6

6.6

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

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

Категория
Вызов функций
Уровень
Средний
Связанные темы
Аргументы, списки, кортежи, словари
Зачем это знать
Передавать готовые коллекции и собирать новые

§1Одинаковые символы — два направления

Где запись***
в параметрах defсобирает позиционные аргументы в кортежсобирает именованные аргументы в словарь
в вызове функциираскладывает итерируемый объект по позициямраскладывает отображение по именам

§2Звёздочка при вызове функции

main.pyсписок превращается в три аргумента
def add(a, b, c):
    return a + b + c

numbers = [1, 2, 3]
print(add(*numbers))
Выводadd(1, 2, 3)
6

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

§3Две звёздочки при вызове

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

main.pyсловарь превращается в name= и age=
def greet(name, age):
    print(name, age)

person = {"name": "Алиса", "age": 30}
greet(**person)
Выводgreet(name="Алиса", age=30)
Алиса 30

§4* и ** в одном вызове

Сначала передаются позиционные аргументы, затем именованные. Один параметр не должен получить значение дважды.

main.pyдве коллекции данных
def show(a, b, c, name):
    print(a, b, c, name)

numbers = [1, 2, 3]
profile = {"name": "Макс"}
show(*numbers, **profile)
Выводчетыре аргумента
1 2 3 Макс

§5Несколько распаковок в вызове

main.pyдве последовательности подряд
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Распаковка внутри списка

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

main.pyобъединение без изменения исходников
left = [1, 2, 3]
right = [4, 5, 6]
numbers = [*left, 0, *right]
print(numbers)
Выводновый список
[1, 2, 3, 0, 4, 5, 6]

§7Распаковка внутри словаря

Две звёздочки копируют пары «ключ — значение». Если ключ повторяется, более позднее значение заменяет предыдущее.

main.pyнастройки пользователя важнее базовых
defaults = {"theme": "light", "size": 14}
user = {"theme": "dark"}
settings = {**defaults, **user}
print(settings)
Выводtheme заменена
{'theme': 'dark', 'size': 14}

§8Распаковка при присваивании

Количество имён должно совпадать с количеством значений.

main.pyтри значения — три имени
red, green, blue = [255, 128, 0]
print(red, green, blue)
Выводотдельные переменные
255 128 0

§9Звёздочка собирает остаток

В присваивании только одно имя может иметь звёздочку. Оно получает список из всех значений, не распределённых между остальными именами.

main.pyпервое, середина и последнее
first, *middle, last = [1, 2, 3, 4, 5]
print(first)
print(middle)
print(last)
Выводmiddle всегда список
1
[2, 3, 4]
5

§10Автоматическая распаковка в цикле

Цикл может сразу разделить каждый элемент на несколько имён. Звёздочка не нужна, если число частей известно.

main.pyкаждый элемент — пара
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 = valuesSyntaxError: две звёздочки в одном присваиваниииспользовать только одну переменную для остатка

§12Проверьте себя

Что делает *items в вызове функции?

Передаёт каждый элемент итерируемого объекта как отдельный позиционный аргумент.

Что требуется от словаря в function(**data)?

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

Какой тип получает имя со звёздочкой при присваивании?

Список со всеми оставшимися элементами.

§13Шпаргалка

Позиции из коллекцииfunction(*items)
Имена из словаряfunction(**data)
Новый список[*left, *right]
Остатокfirst, *rest = items

Итог главы

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

Глава 6.6 · Распаковка аргументов · Справочник по PythonАвтор: Макаров Максим Николаевич