W3docs

Распаковка кортежей в Python: подробное руководство

Распаковка кортежей в Python: базовый синтаксис, звёздные выражения, вложенные кортежи, распаковка в циклах и типичные ошибки.

Распаковка кортежей (также называется распаковкой итерируемых объектов) позволяет присвоить элементы кортежа — или любого итерируемого объекта — отдельным переменным в одном выражении. Эта страница охватывает всё: от базового синтаксиса до продвинутых паттернов, таких как звёздные выражения, вложенная распаковка и распаковка в циклах.

Что такое распаковка кортежей?

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

python— editable, runs on the server

Скобки вокруг кортежа необязательны — 1, 2, 3 тоже является кортежем. Обе следующие строки эквивалентны:

a, b, c = (1, 2, 3)
a, b, c = 1, 2, 3   # same result

Зачем использовать распаковку кортежей?

Лаконичное присваивание переменных

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

python— editable, runs on the server

Обмен значений переменных

Распаковка позволяет поменять два значения местами в одну строку. Python полностью вычисляет правую часть перед присваиванием, поэтому временная переменная не нужна:

python— editable, runs on the server

Чтение возвращаемых значений функций

Функции, возвращающие несколько значений, на самом деле возвращают кортеж. Распаковка позволяет сразу дать каждому значению понятное имя:

def min_max(numbers):
    return min(numbers), max(numbers)

lo, hi = min_max([3, 1, 4, 1, 5, 9, 2, 6])

print(lo)  # 1
print(hi)  # 9

Без распаковки пришлось бы писать result[0] и result[1], что менее читаемо.

Расширенная распаковка с оператором звёздочки

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

Захват хвоста

first, *rest = (1, 2, 3, 4, 5)

print(first)  # 1
print(rest)   # [2, 3, 4, 5]

Захват головы

*start, last = (1, 2, 3, 4, 5)

print(start)  # [1, 2, 3, 4]
print(last)   # 5

Захват средней части

first, *middle, last = (10, 20, 30, 40, 50)

print(first)   # 10
print(middle)  # [20, 30, 40]
print(last)    # 50

В одном выражении распаковки допускается только одна помеченная переменная. Использование двух и более вызывает SyntaxError.

Игнорирование элементов с помощью _

В Python принято использовать _ в качестве имени «мусорной» переменной. Это допустимый идентификатор — Python просто присваивает ему значение, — но по соглашению он сигнализирует: «Это значение мне не нужно».

x, _, z = (10, 99, 30)

print(x)  # 10
print(z)  # 30
# _ holds 99 but we do not use it

Комбинируйте _ со звёздным выражением, чтобы отбросить несколько элементов:

first, *_ = (10, 20, 30, 40)

print(first)  # 10
# *_ swallows 20, 30, 40

Вложенная распаковка кортежей

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

python— editable, runs on the server

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

Распаковка в циклах for

Вы можете распаковывать каждый элемент итерируемого объекта непосредственно в операторе for. Это особенно удобно при работе со списками кортежей:

pairs = [(1, 'one'), (2, 'two'), (3, 'three')]

for num, word in pairs:
    print(num, word)

# 1 one
# 2 two
# 3 three

Распаковка с enumerate()

enumerate() возвращает пары (индекс, значение), которые можно сразу распаковать:

fruits = ('apple', 'banana', 'cherry')

for i, fruit in enumerate(fruits):
    print(i, fruit)

# 0 apple
# 1 banana
# 2 cherry

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

Распаковка с zip()

zip() объединяет элементы двух итерируемых объектов в пары, и каждую пару можно распаковывать в цикле:

names = ('Alice', 'Bob', 'Carol')
scores = (92, 87, 95)

for name, score in zip(names, scores):
    print(name, score)

# Alice 92
# Bob 87
# Carol 95

Распространённые ошибки

Слишком много или слишком мало значений

Python вызывает ValueError, если количество переменных не совпадает с количеством элементов (и звёздное выражение отсутствует):

a, b = (1, 2, 3)
# ValueError: too many values to unpack (expected 2)
a, b, c = (1, 2)
# ValueError: not enough values to unpack (expected 3, got 2)

Устраните несоответствие или используйте звёздное выражение, чтобы поглотить лишние элементы.

Две переменные со звёздочкой

first, *middle, *last = (1, 2, 3, 4)
# SyntaxError: multiple starred expressions in assignment

В одном выражении распаковки допускается только одна переменная с *.

Краткий справочник

ПаттернПримерЧто делает
Базовыйa, b, c = tПрисваивает каждый элемент именованной переменной
Звёздный хвостfirst, *rest = tПервый элемент именован; остаток захватывается как список
Звёздная голова*start, last = tПоследний элемент именован; остаток захватывается как список
Звёздная серединаfirst, *mid, last = tПервый и последний именованы; середина захватывается как список
Игнорировать одинx, _, z = tСредний элемент отбрасывается по соглашению
Игнорировать многиеfirst, *_ = tСохраняется только первый элемент
Вложенныйa, (b, c), d = tВнутренний кортеж распаковывается в том же выражении
Циклfor x, y in pairs:Каждая пара распаковывается на каждой итерации

Связанные главы

  • Python Tuples — создание, индексирование и нарезка кортежей
  • Access Tuples — чтение отдельных элементов по индексу
  • Loop Tuples — итерация по элементам кортежа
  • Join Tuples — объединение нескольких кортежей
  • Tuple Methodscount() и index()
  • Update Tuples — работа с неизменяемостью

Практика

Практика
What does Python assign to the starred variable when you write `first, *rest = (1, 2, 3, 4, 5)`?
What does Python assign to the starred variable when you write `first, *rest = (1, 2, 3, 4, 5)`?
Was this page helpful?