Почему я получаю сообщение об ошибке Python «Too Many Values To Unpack»?

Ошибка Python «Too Many Values To Unpack» возникает, когда вы пытаетесь извлечь несколько значений из структуры данных в переменные, количество которых не соответствует количеству значений. Например, если вы попытаетесь распаковать элементы списка в переменные, количество которых не соответствует количеству элементов в списке.

Мы вместе рассмотрим некоторые сценарии возникновения этой ошибки, например, при распаковке списков, словарей или при вызове функций Python.

Как исправить ошибку «Too Many Values To Unpack» в Python

Распространенный сценарий, в котором возникает ошибка «слишком много значений для распаковки», — это когда вы пытаетесь распаковать значения из списка Python.

Давайте посмотрим простой пример:

>>> week_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
>>> day1, day2, day3 = week_days

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

Ошибка жалуется на то, что значений в правой части выражения слишком много, чтобы их можно было присвоить трем переменным day1, day2и day3.

Как видно из трассировки, это ошибка типа ValueError.

Итак, что мы можем сделать, чтобы исправить эту ошибку?

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

>>> day1, day2, day3, day4, day5 = week_days
>>> day1
'Monday'
>>> day5
'Friday'

На этот раз ошибки нет, и каждая переменная имеет одно из значений внутри массива week_days.

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

Давайте посмотрим, что произойдет, если у вас недостаточно значений для присвоения переменным:

>>> weekend_days = ['Saturday', 'Sunday']
>>> day1, day2, day3 = weekend_days

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)

В этом примере мы пытаемся присвоить два значения трем переменным day1, day2 и day3.

Вот почему ошибка говорит: «Недостаточно значений для распаковки (ожидалось 3, получено 2)». Потому что Python ожидает, что переменным слева будут присвоены 3 значения, но он получил только 2 значения.

В этом случае правильным выражением будет:

>>> day1, day2 = weekend_days

ValueError при вызове функции Python

Та же ошибка может возникнуть при неправильном вызове функции Python.

Я определю простую функцию, которая принимает на вход число x и возвращает на выходе два числа: квадрат и куб x.

>>> def getSquareAndCube(x):
        return x**2, x**3 
>>> square, cube = getSquareAndCube(2)
>>> square
4
>>> cube
8

Что произойдет, если мы по ошибке присвоим значения, возвращаемые функцией, трем переменным вместо двух?

>>> square, cube, other = getSquareAndCube(2)

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)

Мы видим ошибку «недостаточно значений для распаковки», поскольку значений для распаковки — два, а переменных в левой части выражения — три.

А что, если вы присвоите вывод функции одной переменной?

>>> output = getSquareAndCube(2)
>>> output
(4, 8)

Все работает хорошо, и Python превращает выходную переменную в кортеж, содержащий оба значения, возвращаемые функцией getSquareAndCube().

Слишком много значений для распаковки при использовании функции ввода

Другой распространенный сценарий, в котором может возникнуть эта ошибка, — это использование функции Python input(), чтобы попросить пользователей предоставить входные данные.

Функция Python input() считывает вводимые пользователем данные и преобразует их в строку перед возвратом.

Вот простой пример:

>>> name, surname = input("Enter your name and surname: ")
Enter your name and surname: John Smith

Traceback (most recent call last):
     File "<pyshell#4>", line 1, in <module>
     name, surname = input("Enter your name and surname: ")
ValueError: too many values to unpack (expected 2)

Почему Python жалуется на слишком много значений для распаковки?

Это связано с тем, что функция input() преобразует входные данные в строку, в данном случае «Джон Смит», а затем пытается присвоить каждый символ строки переменным слева.

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

Что мы можем с этим поделать?

Мы можем применить строковый метод Split() к выводу функции ввода:

>>> name, surname = input("Enter your name and surname: ").split()
Enter your name and surname: John Smith
>>> name
'John'
>>> surname
'Smith'

Метод разделения преобразует строку, возвращаемую функцией ввода, в список строк, и два элемента списка присваиваются переменным имени и фамилии.

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

Использование Maxsplit для решения ошибки Python «слишком много значений для распаковки»

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

Начнем снова со следующего кода:

>>> name, surname = input("Enter your name and surname: ").split()

На этот раз мы предоставим другую строку для входной функции:

Enter your name and surname: Mr John Smith

Traceback (most recent call last):
    File "<pyshell#29>", line 1, in <module>
    name, surname = input("Enter your name and surname: ").split()
ValueError: too many values to unpack (expected 2)

Аналогично, как мы видели ранее, эта ошибка возникает из-за того, что функция Split() преобразует входную строку в список из трех элементов. И три элемента не могут быть присвоены двум переменным.

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

Вот общий синтаксис метода Split(), который позволяет это сделать:

<string>.split(separator, maxsplit)

Параметр maxsplit определяет максимальное количество разбиений, используемых методом разделения Python при преобразовании строки в список. Maxsplit — необязательный параметр.

Итак, в нашем случае давайте посмотрим, что произойдет, если мы установим maxsplit равным 1.

>>> name, surname = input("Enter your name and surname: ").split(' ', 1)

Enter your name and surname: Mr John Smith
>>> name
'Mr'
>>> surname
'John Smith'

Ошибка исчезла, логика этой строки не идеальна, учитывая, что surname это «Джон Смит». Но это всего лишь пример, показывающий, как работает maxsplit.

Итак, почему мы устанавливаем maxsplit равным 1?

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

Слишком много значений для распаковки при переборе словаря

В последнем примере мы будем использовать словарь Python, чтобы объяснить еще одну распространенную ошибку, которая возникает во время разработки.

Я создал простую программу для печати каждого ключа и значения в словаре users:

users = {
     'username': 'jsmith',
     'name': 'John',
}

for key, value in users:
     print(key, value)

При запуске вы видите следующую ошибку:

$ python dict_example.py

Traceback (most recent call last):
    File "dict_example.py", line 6, in <module>
    for key, value in users:
ValueError: too many values to unpack (expected 2)

В чем проблема?

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

for key in users:
    print(key)

Результат:

$ python dict_example.py
username
name

Когда мы просматриваем словарь, используя его имя, мы получаем только ключи.

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

Чтобы получить каждый ключ и значение из словаря, нам нужно использовать метод elements() словаря.

Давайте запустим следующее:

for user in users.items():
    print(user)

На этот раз результат:

('username', 'jsmith')
('name', 'John')

На каждой итерации цикла for мы получаем кортеж, содержащий ключ и его значение. Этот кортеж можно присвоить двум переменным, которые мы использовали ранее.

Итак, программа становится:

users = {
    'username': 'jsmith',
    'name': 'John',
}

for key, value in users.items():
    print(key, value)

Программа печатает следующий вывод:

$ python dict_example.py
username jsmith
name John

Все отлично, ошибка исправлена!

А ты? Где вы видите эту ошибку?

Позвольте мне знать в комментариях ниже.