Valueerror not enough values to unpack ошибка

Ну, что же давайте разберем.

Документация по argv можно найти на сайте с документацией. Другими словами argv будет содержать аргументы командной строки.

Проубем запустить ваш код с одним лишь добавлением строки вывода с содержанием самого argv

from sys import argv
print(argv) # здесь смотрим, что содержит argv
script, filename = argv
txt = open(filename)
print(f"Содержимое файла {filename}:")
print(txt.read())
print("Снова введите имя файла:")
file_again = input("> ")
txt_again = open(file_again)
print(txt_again.read())

вызов

C:...> py t.py

вывод ожидаемо (файл t.py у меня)

['t.py']
Traceback (most recent call last):
  File "C:...t.py", line 3, in <module>
    script, filename = argv
ValueError: not enough values to unpack (expected 2, got 1)

Ошибка говорит, что у вас не достаточно аргументнов передано из командной строки. Т.е. ожидается 2, но получено всего лишь 1. Это можно увидеть в выводе содержания argv. А теперь передадим при запуске файла t.py дополнительный аргумент, который ожидается распаковкой script, filename = argv.

Ну так давайте передадим дополнительный аргумент. Вызов:

py t.py t.py

Вывод

C:...>py t.py t.py
['t.py', 't.py']
Содержимое файла t.py:
Traceback (most recent call last):
  File "C:...t.py", line 6, in <module>
    print(txt.read())
  File "C:...cp1252.py", line 23, in decode
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 194: character maps to <undefined>

Работа уже дошла до строки, которая содержит print(txt.read()). Это не мое дело, поэтому просто закомментирую ее и запущу по новой:

C:...>py t.py t.py
['t.py', 't.py']
Содержимое файла t.py:
Снова введите имя файла:
>

Результат, который вы ожидаете, наверное.

PS: я абослютно не вдавался в логику ваших действий. Я скорее показал метод, как поправить некорректное поведение.

UPD

если не игнорировать ошибку кодировки, то конечное решение:

from sys import argv
script, filename = argv
txt = open(filename,  encoding="utf8")
print(f"Содержимое файла {filename}:")
print(txt.read())
print("Снова введите имя файла:")
file_again = input("> ")
txt_again = open(file_again, encoding="utf8")
print(txt_again.read())

Вызов:

C:...>py t.py test_read.txt

Вывод:

Содержимое файла test_read.txt:
line 1
line 2
here is line 3
Снова введите имя файла:
>

  1. What Is a ValueError in Python
  2. Fix ValueError: not enough values to unpack in Python Dictionaries
  3. Fix ValueError: not enough values to unpack in Python

ValueError: Not Enough Values to Unpack in Python

It is a common error when you are freshly getting your hands dirty with Python programming, or sometimes it could be a type error that you provide more values but fewer variables (containers) to catch those values. Or when you try to iterate over a dictionary’s values or keys but try to access both simultaneously.

This article will look at each scenario in detail along with examples but before that, let’s understand what a ValueError is in Python.

What Is a ValueError in Python

A ValueError is a common exception in Python that occurs when the number of values doesn’t match the number of variables either taking input, direct assignment or through an array or accessing restricted values. To understand the ValueError, let’s take an example.

# this input statement expects three values as input
x,y,z = input("Enter values for x, y and z: ").split(",")

Output:

Enter values for x, y and z: 1,2
ValueError: not enough values to unpack (expected 3, got 2)

In the above example, we have three variables x,y,z to catch the input values, but we provide two input values to demonstrate the ValueError.

Now the input statement has three values, and since the user input values do not meet the expected condition, it throws the ValueError: not enough values to unpack (expected 3, got 2).

The error itself is self-explanatory; it tells us that the expected number of values is three, but you have provided 2.

A few other common causes of ValueError could be the following.

a,b,c = 3, 5      #ValueError: not enough values to unpack (expected 3, got 2)
a,b,c = 2  		  #ValueError: not enough values to unpack (expected 3, got 1)
a,b,d,e = [1,2,3] #ValueError: not enough values to unpack (expected 4, got 3)

Fix ValueError: not enough values to unpack in Python Dictionaries

In Python, a dictionary is another data structure whose elements are in key-value pairs, every key should have a corresponding value against the key, and you can access the values with their keys.

Syntax of a dictionary in Python:

student = {
    "name"    : "Zeeshan Afridi",
    "degree"  : "BSSE",
    "section" : "A"
}

This is the general structure of a dictionary; the values of the left are keys, whereas the others are values of the keys.

We have specified functions for Python, dictionaries like keys(), values(), items(), etc. But these are the most common and useful functions to loop through a dictionary.

print("Keys of Student dictionary: ", student.keys())
print("Values of Student dictionary: ", student.values())
print("Items of Student dictionary: ", student.items())

Output:

Keys of Student dictionary:  dict_keys(['name', 'degree', 'section'])
Values of Student dictionary:  dict_values(['Zeeshan Afridi', 'BSSE', 'A'])
Items of Student dictionary:  dict_items([('name', 'Zeeshan Afridi'), ('degree', 'BSSE'), ('section', 'A')])

Let’s see why the ValueError: not enough values to unpack occurs in Python dictionaries.

student = {
    #Keys     :  Values
    "name"    : "Zeeshan Afridi",
    "degree"  : "BSSE",
    "section" : "A"
}

#iterate user dictionary
for k,v,l in student.items(): # This statement throws an error
    print("Key:", k)
    print("Value:", str(v))

Output:

ValueError: not enough values to unpack (expected 3, got 2)

As you can see, the above code has thrown an error because the .items() functions expect two variables to catch the keys and values of the student dictionary, but we have provided three variables k,v,l.

So there isn’t any space for l in the student dictionary, and it throws the ValueError: not enough values to unpack (expected 3, got 2).

To fix this, you need to fix the variables of the dictionary.

for k,v in student.items()

This is the correct statement to iterate over a dictionary in Python.

Fix ValueError: not enough values to unpack in Python

To avoid such exceptions in Python, you should provide the expected number of values to the variables and display useful messages to guide yours during entering data into forms or any text fields.

In addition to that, you can use try-catch blocks to capture such errors before crashing your programs.

Let’s understand how to fix the ValueError: not enough values to unpack in Python.

# User message --> Enter three numbers to multiply  ::
x,y,z = input("Enter three numbers to multiply  ::  ").split(",")

# type casting x,y, and z
x = int(x)
y = int(y)
z = int(z)

prod = (x*y*z)

print("The product of x,y and z is  :: ",prod)

Output:

Enter three numbers to multiply  ::  2,2,2
The product of x,y and z is  ::  8

Here in this example, the input statement expects three inputs, and we have provided the expected number of inputs, so it didn’t throw any ValueError.

In Python, the ValueError: not enough values to unpack occurs if you try to unpack fewer values than the number of variables you have assigned to them. For example, if you’re trying to unpack a list with two values in three variables. This error is commonly encountered when working with lists, tuples, and dictionaries.

ValueError not enough values to unpack

In this tutorial, we will look at the common scenarios in which this error occurs and what you can do to resolve it.

Understanding ValueError: not enough values to unpack the error

This error occurs when you try to unpack fewer values in more variables. Before we dive into the error, let’s see what unpacking is.

What is unpacking in Python?

In Python, unpacking refers to the process of extracting values from an iterable (e.g. list, tuple, dictionary) and assigning them to separate variables in a single statement.

For example, consider the following list:

my_list = [1, 2, 3]

We can unpack the values in my_list and assign them to separate variables like this:

a, b, c = my_list

Now, a will be assigned the value 1, b will be assigned the value 2, and c will be assigned the value 3. Similarly, you can unpack other iterables like tuples and dictionaries.

Unpacking can also be used with functions that return multiple values. For example:

def my_function():
    return 1, 2, 3

a, b, c = my_function()

Now, a will be assigned the value 1, b will be assigned the value 2, and c will be assigned the value 3.

Why does this error occur?

When unpacking an iterable, Python expects you to provide the same number of variables as there are values in the iterable you are unpacking. If you use more variables, you’ll encounter the ValueError: not enough values to unpack error.

Let’s look at an example.

# create a list with two values
my_list = [1, 2]
# unpack the list values
a, b, c = my_list

Output:

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[1], line 4
      2 my_list = [1, 2]
      3 # unpack the list values
----> 4 a, b, c = my_list

ValueError: not enough values to unpack (expected 3, got 2)

In the above example, we try to unpack a list with two values in three variables – a, b, and c since the number of variables is more than the number of values to unpack, we get the error, ValueError: not enough values to unpack (expected 3, got 2).

You’ll similarly get this error when unpacking less number of values than the variables you’re using to unpack those values in other iterables like tuples, dictionaries, etc.

Another common scenario in which this error occurs is when unpacking the return values from a function. Let’s look at an example.

# function to get descriptive stats of a list of values
def calculate_statistics(numbers):
    """
    This function takes a list of numbers as input and returns the mean, median, and mode.
    """
    mean = sum(numbers) / len(numbers)

    sorted_numbers = sorted(numbers)
    middle_index = len(numbers) // 2

    if len(numbers) % 2 == 0:
        median = (sorted_numbers[middle_index - 1] + sorted_numbers[middle_index]) / 2
    else:
        median = sorted_numbers[middle_index]

    return mean, median

# list of numbers
numbers = [1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 9]
# call the function
mean, median, mode = calculate_statistics(numbers)
print("Mean:", mean)
print("Median:", median)
print("Mode:", mode)

Output:

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[2], line 22
     20 numbers = [1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 9]
     21 # call the function
---> 22 mean, median, mode = calculate_statistics(numbers)
     23 print("Mean:", mean)
     24 print("Median:", median)

ValueError: not enough values to unpack (expected 3, got 2)

In the above example, we have a function called calculate_statistics() that returns the mean and the median of a list of numbers. We tried to unpack the return value from the function in three variables (which is more than the number of values being returned from the function) and thus we get the error.

How to fix this error?

To fix the ValueError: not enough values to unpack error, make sure that you are using the same number of variables as there are values in the iterable you are trying to unpack.

Let’s revisit the examples from above and fix them.

# create a list with two values
my_list = [1, 2]
# unpack the list values
a, b = my_list

In the above example, we did not get any errors since we are using two variables – a and b to unpack a list with two values.

Note that if you do not have any use for one or more values from the iterable that you’re unpacking, you can use _ as a placeholder. For example, in the above scenario, let’s say the list has three values and we do not need that last value from the list thus there’s no requirement to save it in a variable. In that case, you can use _ in place of a third variable.

# create a list with three values
my_list = [1, 2, 3]
# unpack the list values
a, b, _ = my_list

We don’t get an error here. Note that you can use _ more than once as well in the same unpacking statement, if you do not want multiple values resulting from unpacking the given iterable.

Let’s now fix the function example.

# function to get descriptive stats of a list of values
def calculate_statistics(numbers):
    """
    This function takes a list of numbers as input and returns the mean, median, and mode.
    """
    mean = sum(numbers) / len(numbers)

    sorted_numbers = sorted(numbers)
    middle_index = len(numbers) // 2

    if len(numbers) % 2 == 0:
        median = (sorted_numbers[middle_index - 1] + sorted_numbers[middle_index]) / 2
    else:
        median = sorted_numbers[middle_index]

    return mean, median

# list of numbers
numbers = [1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 9]
# call the function
mean, median = calculate_statistics(numbers)
print("Mean:", mean)
print("Median:", median)

Output:

Mean: 5.166666666666667
Median: 5.5

In the above example, we are using the same number of variables (two) as the number of values being returned from the calculate_statistics() function. You can see that we did not get an error here.

Conclusion

The ValueError: not enough values to unpack error occurs when you try to unpack fewer values than the number of variables you have assigned to them. To fix this error, you need to make sure the number of variables you have assigned to the values you are trying to unpack is equal to the number of values you are trying to unpack.

  • Piyush Raj

    Piyush is a data professional passionate about using data to understand things better and make informed decisions. He has experience working as a Data Scientist in the consulting domain and holds an engineering degree from IIT Roorkee. His hobbies include watching cricket, reading, and working on side projects.

    View all posts

If you’re a Python developer, you might have come across the error message «ValueError: not enough values to unpack (expected 2, got 1)» at some point. This error occurs when you try to unpack a tuple or a list with fewer items than expected.

In this guide, we’ll explore the possible causes of this error and provide step-by-step solutions to fix it.

Causes of the ‘not enough values to unpack’ Error

The ‘not enough values to unpack’ error usually occurs when you try to unpack a tuple or a list with fewer items than expected. For example, let’s say you have a tuple with two items, but you try to unpack it into three variables:

a, b, c = (1, 2)

In this case, you’ll get the following error message:

ValueError: not enough values to unpack (expected 3, got 2)

Another common cause of this error is when you try to unpack a non-iterable object, such as an integer or a float. For example:

a, b = 1

This will result in the following error message:

TypeError: cannot unpack non-iterable int object

How to Fix the ‘not enough values to unpack’ Error

To fix the ‘not enough values to unpack’ error, you need to make sure that the tuple or list you’re unpacking has the same number of items as the number of variables you’re trying to unpack it into.

Here are some possible solutions:

Solution 1: Check the Number of Items in the Tuple or List

The first step is to check the number of items in the tuple or list you’re trying to unpack. You can do this by using the len() function:

my_tuple = (1, 2)
print(len(my_tuple))  # Output: 2

If the number of items in the tuple or list is less than the number of variables you’re trying to unpack it into, you’ll need to modify your code accordingly.

Solution 2: Use a Default Value for the Missing Item

If you’re trying to unpack a tuple or list with a variable number of items, you can use a default value for the missing item:

a, b, c = (1, 2)
c = c if len(my_tuple) >= 3 else None

In this example, if the tuple has fewer than three items, c will be set to None.

Solution 3: Use the * Operator to Capture Remaining Items

If you’re trying to unpack a tuple or list with a variable number of items, you can use the * operator to capture the remaining items:

a, b, *c = (1, 2, 3, 4, 5)
print(c)  # Output: [3, 4, 5]

In this example, a will be set to 1, b will be set to 2, and c will be a list containing the remaining items.

FAQ

Q1: What does the ‘not enough values to unpack’ error mean?

A: The ‘not enough values to unpack’ error occurs when you try to unpack a tuple or a list with fewer items than expected.

Q2: How do I fix the ‘not enough values to unpack’ error?

A: To fix the error, you need to make sure that the tuple or list you’re unpacking has the same number of items as the number of variables you’re trying to unpack it into.

Q3: Why am I getting a ‘TypeError: cannot unpack non-iterable int object’ error?

A: This error occurs when you try to unpack a non-iterable object, such as an integer or a float.

Q4: How can I check the number of items in a tuple or list?

A: You can use the len() function to check the number of items in a tuple or list.

Q5: How can I capture the remaining items in a tuple or list?

A: You can use the * operator to capture the remaining items in a tuple or list.

Unpacking syntax lets you separate the values from iterable objects. If you try to unpack more values than the total that exist in an iterable object, you’ll encounter the “ValueError: not enough values to unpack” error.

This guide discusses what this error means and why you may see it in your code. We’ll walk through an example of this error in action so you can see how it works.

Get offers and scholarships from top coding schools illustration

Find Your Bootcamp Match

  • Career Karma matches you with top tech bootcamps
  • Access exclusive scholarships and prep courses

Select your interest

First name

Last name

Email

Phone number

By continuing you agree to our Terms of Service and Privacy Policy, and you consent to receive offers and opportunities from Career Karma by telephone, text message, and email.

ValueError: not enough values to unpack

Iterable objects like lists can be “unpacked”. This lets you assign the values from an iterable object into multiple variables.

Unpacking is common when you want to retrieve multiple values from the response of a function call, when you want to split a list into two or more variables depending on the position of the items in the list, or when you want to iterate over a dictionary using the items() method.

Consider the following example:

name, address = ["John Doe", "123 Main Street"]

This code unpacks the values from our list into two variables: name and address. The variable “name” will be given the value “John Doe” and the variable address will be assigned the value “123 Main Street”.

You have to unpack every item in an iterable if you use unpacking. You cannot unpack fewer or more values than exist in an iterable. This is because Python would not know which values should be assigned to which variables.

An Example Scenario

We’re going to write a program that calculates the total sales of a product at a cheese store on a given day. To start, we’re going to ask the user to insert two pieces of information: the name of a cheese and a list of all the sales that have been made.

We can do this using an input() statement:

name = input("Enter the name of a cheese: ")
sales = input("Enter a comma-separated list of all purchases made of this cheese: ")

Our “sales” variable expects the user to insert a list of sales. Each value should be separated using a comma.

Next, define a function that calculates the total of all the sales made for a particular cheese. This function will also designate a cheese as a “top seller” if more than $50 has been sold in the last day.

def calculate_total_sales(sales):
	    split_sales = [float(x) for x in sales.split(",")]
	    total_sales = sum(split_sales)
	    if total_sales > 50.00:
		         top_seller = True
	    else:
	  	         top_seller = False

	    return [total_sales]

The split() method turns the values the user gives us into a list. We use a list comprehension to turn each value from our string into a float and put that number in a list.

We use the sum() method to calculate the total value of all the purchases for a given cheese based on the list that the split() method returns. We then use an if statement to determine whether a cheese is a top seller.

Our method returns an iterable with one item: the total sales made. We return an iterable so we can unpack it later in our program. Next, call our function:

total_sales, top_seller = calculate_total_sales(sales)

Our function accepts one parameter: the list of purchases. We unpack the result of our function into two parts: total_sales and top_seller.

Finally, print out the values that our function calculates:

print("Total Sales: $" + str(round(total_sales, 2))
print("Top Seller: " + str(top_seller))

We convert our variables to strings so we can concatenate them to our labels. We round the value of “total_sales” to two decimal places using the round() method. Let’s run our program and see if it works:

Enter the name of a cheese: Edam
Enter a comma-separated list of all purchases made of this cheese: 2.20, 2.90, 3.30
Traceback (most recent call last):
  File "main.py", line 15, in <module>
	total_sales, top_seller = calculate_total_sales(sales)
ValueError: not enough values to unpack (expected 2, got 1)

Our program fails to execute.

The Solution

The calculate_total_sales() function only returns one value: the total value of all the sales made of a particular cheese. However, we are trying to unpack two values from that function.

This causes an error because Python is expecting a second value to unpack. To solve this error, we have to return the “top_seller” value into our main program:

def calculate_total_sales(sales):
	    split_sales = [float(x) for x in sales.split(",")]
	    total_sales = sum(split_sales)
	    if total_sales > 50.00:
		         top_seller = True
	    else:
		         top_seller = False

	    return [total_sales, top_seller]

Our function now returns a list with two values: total_sales and top_seller. These two values can be unpacked by our program because they appear in a list. Let’s run our program and see if it works:

Enter the name of a cheese: Edam
Enter a comma-separated list of all purchases made of this cheese: 2.20, 2.90, 3.30
Total Sales: $8.4
Top Seller: False

Our program now successfully displays the total sales of a cheese and whether that cheese is a top seller to the console.

Conclusion

The “ValueError: not enough values to unpack” error is raised when you try to unpack more values from an iterable object than those that exist. To fix this error, make sure the number of values you unpack from an iterable is equal to the number of values in that iterable.

Now you have the knowledge you need to fix this common Python error like an expert!

ValueError: not enough values to unpack (expected 2, got 1) might appear when you don’t fulfill the expectations of functions regarding their arguments. You either miss the arguments or fail at considering their correct data type.valueerror not enough values to unpack expected 2 got 1 1

Whatever the situation, you don’t need to stress about it because this article explains the causes and solutions for the same error in detail by targeting a variety of functions.

Keep reading to find out where you are going against Python functions’ expectations and how you can satisfy them to eliminate the given error.

Contents

  • What Can Lead You To the ValueError: Not Enough Values To Unpack?
    • – Insufficient or Incorrectly Provided Arguments
    • – Script Arguments Not Found
  • Best Solutions for the ValueError: Not Enough Values To Unpack
    • – Edit the Function Body and Handle the Error
    • – Ensure To Provide Sufficient and Correct Arguments
    • – Come up With the Script Arguments
  • Conclusion

What Can Lead You To the ValueError: Not Enough Values To Unpack?

The ValueError: not enough values to unpack can occur due to passing insufficient or incorrect arguments to the user-defined or built-in functions in Python. Along with this, if you run an argument-demanding script without any arguments, you’ll receive the same error on your screen.

– Insufficient or Incorrectly Provided Arguments

If you pass insufficient or incorrectly arguments to the functions in Python, the given value error will show up on your screen. The error statement suggests that your program hasn’t received enough values to unpack and set the required parameters for properly executing the function.

The above-stated problem stays valid for all functions, including the user-defined and built-in functions. For example, you have created a custom function that accepts a dictionary and a list of tuples, with each tuple presenting a key-value pair.

The function body adds the provided list of key-value pairs to the dictionary. Now, if you call the same function with a list of tuples that do no contain key-value pairs, you’ll see the ValueError: not enough values to unpack (expected 2, got 1) tuple on your screen.

Similarly, consider using wget to save your favorite images. If you don’t pass the correct source and local path for the image you are downloading, the ValueError: not enough values to unpack (expected 2, got 1) wget will pop up in front of you.

Besides this, say you are working with the matplotlib library and executing the pcolormesh() function. You might get the ValueError not enough values to unpack (expected 2, got 1) matplotlib when you pass incorrect arguments to the given function.

Note that even passing the quadrilaterals without wrapping them in a list can put you in trouble. Although such mistakes might go unnoticed, you can’t proceed further without correcting them.ValueError Not Enough Values To Unpack Expected 2 Got 1 Causes

A similar argument issue can occur with the zip() function and while loading a trained yolov5 model on a custom dataset. Please consider a zip() function example case where you are passing values that begin with a special character, such as a hash to the said function.

Such values are referred to as hash terms. Now, if you keep getting the Valueerror: not enough values to unpack (expected 2, got 1) zip, the cause might be the hash terms not accepted as arguments.

Moreover, the ValueError: not enough values to unpack (expected 2, got 1) yolov5 can result due to leaving the source argument to its default setting while loading the trained yolov5 model. By default, the said argument is set to GitHub. Thus, your program will look for the GitHub repository and return an error on being unable to find it.

– Script Arguments Not Found

If your script accepts a few arguments and you don’t provide the required argument while running the same script, you’ll encounter the ValueError: not enough values to unpack (expected 2, got 1) argv. Here, argv can be any identifier that stores the said arguments.

For example, you have created a script that requires three arguments for running it. Now, if you run the same script without passing any arguments, the script execution will fail abruptly with the stated error. Remember that it doesn’t matter if you are running the script through the command line or in PyCharm, the arguments will be needed anyways.

A script that demands arguments will be similar to the one attached below.

from sys import argv

script, one, two = argv

print(“The script name: “, script)

print(“The first variable: “, one)

print(“The second variable: “, two)

Best Solutions for the ValueError: Not Enough Values To Unpack

The best solutions to eliminate the ValueError: not enough values to unpack error, include handling the error inside the body of a user-defined function and passing sufficient and correct arguments. Moreover, passing the arguments while running an argument-demanding script can be helpful.



– Edit the Function Body and Handle the Error

For the custom or user-defined functions, you can edit the function body to process the arguments in the try block. Next, you can create and use the except block to handle the above error in case of wrong or insufficient arguments.

Pointing toward the custom function discussed earlier, you can unpack a key-value tuple inside the try block. Consequently, if the tuple contains a key-value pair, the key and value will be stored in their respective identifiers. In the other case, the except block will be executed, informing you about the insufficient length of the tuple.

The coding snippet that depicts the given scenario can be seen below.

def add_more(d, pairs):

mylist = []

for pair in pairs:

try:

a, b = pair

except (ValueError):

tuple_len = len(pair)

raise RuntimeError(”Wrong argument ‘pairs’!

The key-value pair is corrupted with ({}) length!”’.format(tuple_len))

– Ensure To Provide Sufficient and Correct Arguments

Before you call a function in your script, it would be best to go through its definition to know about the arguments it requires and their types. This way, you’ll never fall into the trap of incorrect or insufficient arguments errors like the one discussed in this post.Ensure To Provide Sufficient and Correct Arguments

So whether it is wget.download(), pcolormesh(), zip(), or the load() function, you’ll have to keep an eye on its definition. If you study its definition and follow the correct sequence of the arguments with the perfect types, you’ll never see the same error again.

Being specific about loading the trained yolov5 model on a custom dataset, setting the src argument to “local” will resolve the error. The local source specified will make your program look for the path on your local file system leading to zero issues in the finding process.

– Come up With the Script Arguments

Providing the required number of arguments while running a specific script will push away the ValueError: not enough values to unpack (expected 2, got 1) Django. You can pass the necessary arguments through the command line or PyCharm as per your preference.

Consider that your script accepts three arguments. You’ll need to run it in the command line like python yourscript.py arg1 arg2 arg3. However, if you are using PyCharm, you’ll have to configure arguments in the same. Here are a few steps that’ll help you out.

  1. Click Run.
  2. Hit Edit Configurations.
  3. Create a new Python configuration.
  4. Add the arguments in the Script parameters field.

Conclusion

The ValueError: not enough values to unpack (expected 2, got 1) is generated when the functions aren’t happy with the arguments you’ve passed. You might think that the arguments are sufficient and correct, but if the same error comes up, there must be some unclarity regarding the function definition on your side.

Here are some noteworthy points from this article that’ll help you kick away the said error instantly.

  • Add the code that might throw the given error inside the try block in your custom function’s body and handle the stated error through the except block.
  • Always double-check the function definition before executing it to avoid passing problematic arguments and solve the same error.
  • It would be best to pass the necessary arguments while running a script that demands arguments to stay away from the given Python error.
  • You can pass the arguments while running the script through the command line or PyCharm at your convenience.

Learning about your function’s required arguments and executing the function flawlessly is key to resolving the value error within seconds.

  • Author
  • Recent Posts

Position is Everything

Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL. Meet The Team

Position is Everything

The error “too many values to unpack” is common in Python, you might have seen it while working with lists.

The Python error “too many values to unpack” occurs when you try to extract a number of values from a data structure into variables that don’t match the number of values. For example, if you try to unpack the elements of a list into variables whose number doesn’t match the number of elements in the list.

We will look together at some scenarios in which this error occurs, for example when unpacking lists, dictionaries or when calling Python functions.

By the end of this tutorial you will know how to fix this error if you happen to see it.

Let’s get started!

How Do You Fix the Too Many Values to Unpack Error in Python

What causes the too many values to unpack error?

This happens, for example, when you try to unpack values from a list.

Let’s see a simple example:

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

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

The error complains about the fact that the values on the right side of the expression are too many to be assigned to the variables day1, day2 and day3.

As you can see from the traceback this is an error of type ValueError.

So, what can we do?

One option could be to use a number of variables on the left that matches the number of values to unpack, in this case seven:

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

This time there’s no error and each variable has one of the values inside the week_days array.

In this example the error was raised because we had too many values to assign to the variables in our expression.

Let’s see what happens if we don’t have enough values to assign to variables:

>>> 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)

This time we only have two values and we are trying to assign them to the three variables day1, day2 and day3.

That’s why the error says that it’s expecting 3 values but it only got 2.

In this case the correct expression would be:

>>> day1, day2 = weekend_days

Makes sense?

Another Error When Calling a Python Function

The same error can occur when you call a Python function incorrectly.

I will define a simple function that takes a number as input, x, and returns as output two numbers, the square and the cube of x.

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

What happens if, by mistake, I assign the values returned by the function to three variables instead of two?

>>> 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)

We see the error “not enough values to unpack” because the value to unpack are two but the variables on the left side of the expression are three.

And what if I assign the output of the function to a single variable?

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

Everything works well and Python makes the ouput variable a tuple that contains both values returned by the getSquareAndCube function.

Too Many Values to Unpack With the Input Function

Another common scenario in which this error can occur is when you use the Python input() function to ask users to provide inputs.

The Python input() function reads the input from the user and it converts it into a string before returning it.

Here’s a simple example:

>>> name, surname = input("Enter your name and surname: ")
Enter your name and surname: Claudio Sabato

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)

Wait a minute, what’s happening here?

Why Python is complaining about too many values to unpack?

That’s because the input() function converts the input into a string, in this case “Claudio Sabato”, and then it tries to assign each character of the string to the variables on the left.

So we have multiple characters on the right part of the expression being assigned to two variables, that’s why Python is saying that it expects two values.

What can we do about it?

We can apply the string method split() to the ouput of the input function:

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

The split method converts the string returned by the input function into a list of strings and the two elements of the list get assigned to the variables name and surname.

By default, the split method uses the space as separator. If you want to use a different separator you can pass it as first parameter to the split method.

Using Maxsplit to Solve This Python Error

There is also another way to solve the problem we have observed while unpacking the values of a list.

Let’s start again from the following code:

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

This time I will provide a different string to the input function:

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)

In a similar way as we have seen before, this error occurs because split converts the input string into a list of three elements. And three elements cannot be assigned to two variables.

There’s a way to tell Python to split the string returned by the input function into a number of values that matches the number of variables, in this case two.

Here is the generic syntax for the split method that allows to do that:

<string>.split(separator, maxsplit)

The maxsplit parameter defines the maximum number of splits to be used by the Python split method when converting a string into a list. Maxsplit is an optional parameter.

So, in our case, let’s see what happens if we set maxsplit to 1.

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

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

The error is gone, the logic of this line is not perfect considering that surname is ‘John Smith’. But this is just an example to show how maxsplit works.

So, why are we setting maxsplit to 1?

Because in this way the string returned by the input function is only split once when being converted into a list, this means the result is a list with two elements (matching the two variables on the left of our expression).

Too Many Values to Unpack with Python Dictionary

In the last example we will use a Python dictionary to explain another common error that shows up while developing.

I have created a simple program to print every key and value in the users dictionary:

users = {
    'username' : 'codefather',
    'name' : 'Claudio',
}

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

When I run it I see the following error:

$ 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)

Where is the problem?

Let’s try to execute a for loop using just one variable:

for user in users:
    print(user)

The output is:

$ python dict_example.py
username
name

So…

When we loop through a dictionary using its name we get back just the keys.

That’s why we were seeing an error before, we were trying to unpack each key into two variables: key and value.

To retrieve each key and value from a dictionary we need to use the dictionary items() method.

Let’s run the following:

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

This time the output is:

('username', 'codefather')
('name', 'Claudio')

At every iteration of the for loop we get back a tuple that contains a key and its value. This is definitely something we can assign to the two variables we were using before.

So, our program becomes:

users = {
    'username' : 'codefather',
    'name' : 'Claudio',
}

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

The program prints the following output:

$ python dict_example.py
username codefather
name Claudio

All good, the error is fixed!

Conclusion

We have seen few examples that show when the error “too many values to unpack” occurs and how to fix this Python error.

In one of the examples we have also seen the error “not enough values to unpack”.

Both errors are caused by the fact that we are trying to assign a number of values that don’t match the number of variables we assign them to.

And you? Where are you seeing this error?

Let me know in the comments below 🙂

I have also created a Python program that will help you go through the steps in this tutorial. You can download the source code here.

Claudio Sabato - Codefather - Software Engineer and Programming Coach

I’m a Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!

One common error that programmers encounter is the ValueError: Not Enough Values to Unpack (Expected 2, Got 1).

This error typically occurs if we are trying to unpack values from an iterable object, such as a tuple or list, but the number of values expected does not match the number of values received.

In this tutorial, we will explain this ValueError in detail, providing examples to demonstrate its existence and provide practical solutions to resolve it.

Whether you’re a beginner or an experienced Python developer, this article will provide you with the knowledge and techniques to fix this error.

If you encounter the ValueError: not enough values to unpack (expected 2, got 1), it means that you are trying to unpack two values, but the iterable on the right side consists of only one element.

Here’s an example:

a, b = [1]

In this example, we are trying to assign two variables, a and b, with values from a list [1].

However, the list consists of only one element, resulting in a ValueError.

The error message provides additional information, indicating that the code expected two values but received only one.

This error commonly occurs when using unpacking in situations where the number of variables to be assigned does not match the number of values in the iterable.

Let’s see the other examples and their solutions.

Example 1: Unpacking a Tuple with Fewer Values

In this example, we have a tuple (1,), which contains only one element.

However, we are trying to unpack two values into x and y.

As a result, we encounter the error:

Traceback (most recent call last):
File “C:UsersDellPycharmProjectsPython-Code-Examplemain.py”, line 1, in
x, y = (1,)
ValueError: not enough values to unpack (expected 2, got 1)

Solutions to Resolve the ValueError: Not Enough Values to Unpack (Expected 2, Got 1)

Now that we have identified the cause of the ValueError, let’s explore some solutions to resolve it.

By applying the following solutions, you can effectively handle this error and ensure the smooth running of your code.

Solution 1: Check the Length of the Sequence or Collection

Before trying to unpack a sequence or collection, it’s necessary to ensure that it consists of the expected number of values.

You can use the len() function to determine the length of the sequence and compare it to the number of variables you intend to unpack.

Let’s have a look at the example:


my_list = [1]
if len(my_list) == 2:
    a, b = my_list
else:
    print("Insufficient values in the list.")

In this example code, we check the length of my_list using len() before unpacking it.

If the length is as expected (2 in this case), we perform the unpacking.

Otherwise, we handle the case of insufficient values easily.

Solution 2: Use Default Values for Unpacking

Another way to fix the ValueError is to use default values for the variables being unpacked.

This method allows your code to proceed even if the sequence or collection has fewer values than expected.

Let’s see an example:

my_list = [1]
a, b = my_list + [None] * (2 - len(my_list))
print(a, b)

In this example code, we concatenate my_list with a list containing the required number of None values.

By doing this, we ensure that the number of elements being unpacked matches the expected count, even if the original sequence is shorter.

Frequently Asked Questions (FAQs)

What causes the ValueError: Not Enough Values to Unpack (Expected 2, Got 1) error?

This error occurs when we attempt to unpack a sequence or collection into a set number of variables, but the sequence contains fewer values than expected.

Can this error occur with a different number of expected values?

Yes, the error message will vary based on the expected number of values. For example, if you expect three values but receive only two, the error message will reflect that.

How can I fix the ValueError: Not Enough Values to Unpack (Expected 2, Got 1) error?

You can resolve this error by checking the length of the sequence or collection before unpacking it or by using default values for unpacking when the sequence is shorter than expected.

How can I prevent this error from occurring in my code?

To prevent this error, you should carefully validate the length of the sequence or collection before attempting to unpack it, and consider using default values or alternative approaches when dealing with variable-length sequences.

Conclusion

This Valueerror not enough values to unpack expected 2 got 1 error typically occurs when trying to unpack values from an iterable object, such as a tuple or list, but the number of values expected does not match the number of values received.

Through understanding the causes, implementing the recommended solutions, and considering the FAQs, you can enhance your coding skills.

Additional Resources

  • Valueerror invalid literal for int with base 10
  • Valueerror max arg is an empty sequence
  • Valueerror embedded null byte
  • Valueerror: unknown label type: ‘continuous’

Введение Распаковка в Python относится к операции, которая состоит из присвоения итерации значений кортежу [/ lists-vs-tuples-in-python /] (или списку) переменных в одном операторе присваивания. В качестве дополнения можно использовать термин упаковка, когда мы собираем несколько значений в одной переменной с помощью итеративного оператора распаковки *. Исторически сложилось так, что разработчики Python обычно называли этот вид операции распаковкой кортежа. Однако, поскольку эта функция Python оказалась

Вступление

Распаковка в Python относится к операции, которая состоит из
присвоения итерации значений кортежу (или
list ) переменных в одном операторе присваивания. В качестве
дополнения можно использовать термин упаковка , когда мы собираем
несколько значений в одной переменной с помощью итеративного оператора
распаковки * .

Исторически сложилось так, что разработчики Python обычно называли этот
вид операции распаковкой кортежа . Однако, поскольку эта функция
Python оказалась весьма полезной и популярной, она была распространена
на все виды итераций. В наши дни более современным и точным термином
будет итеративная распаковка .

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

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

Упаковка и распаковка в Python

Python позволяет tuple (или list ) переменных слева от операции
присваивания. Каждая переменная в tuple может получать одно значение
(или несколько, если мы используем * ) из итерации в правой части
присваивания.

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

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

Распаковка кортежей

В Python мы можем поместить tuple переменных слева от оператора
присваивания ( = ) и tuple значений справа. Значения справа будут
автоматически присвоены переменным слева в соответствии с их положением
в tuple . В Python это широко известно как распаковка кортежей.
Посмотрите следующий пример:

 >>> (a, b, c) = (1, 2, 3) 
 >>> a 
 1 
 >>> b 
 2 
 >>> c 
 3 

Когда мы помещаем кортежи по обе стороны от оператора присваивания,
происходит операция распаковки кортежа. Значения справа присваиваются
переменным слева в соответствии с их относительным положением в каждом
tuple . Как вы можете видеть в приведенном выше примере, a будет 1
, b будет 2 , а c будет 3 .

Чтобы создать tuple , нам не нужно использовать пару круглых скобок
() качестве разделителей. Это также работает при распаковке кортежей,
поэтому следующие синтаксисы эквивалентны:

 >>> (a, b, c) = 1, 2, 3 
 >>> a, b, c = (1, 2, 3) 
 >>> a, b, c = 1, 2, 3 

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

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

Например, в следующем коде мы используем две переменные слева и три
значения справа. Это вызовет ValueError сообщающую нам, что слишком
много значений для распаковки:

 >>> a, b = 1, 2, 3 
 Traceback (most recent call last): 
 ... 
 ValueError: too many values to unpack (expected 2) 

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

С другой стороны, если мы используем больше переменных, чем значений, мы
получим ValueError но на этот раз сообщение говорит, что недостаточно
значений для распаковки:

 >>> a, b, c = 1, 2 
 Traceback (most recent call last): 
 ... 
 ValueError: not enough values to unpack (expected 3, got 2) 

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

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

Функция распаковки кортежей стала настолько популярной среди
разработчиков Python, что синтаксис был расширен для работы с любым
итеративным объектом. Единственное требование состоит в том, чтобы
итерация давала ровно один элемент для каждой переменной в принимающем
tuple (или list ).

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

 >>> # Unpacking strings 
 >>> a, b, c = '123' 
 >>> a 
 '1' 
 >>> b 
 '2' 
 >>> c 
 '3' 
 >>> # Unpacking lists 
 >>> a, b, c = [1, 2, 3] 
 >>> a 
 1 
 >>> b 
 2 
 >>> c 
 3 
 >>> # Unpacking generators 
 >>> gen = (i ** 2 for i in range(3)) 
 >>> a, b, c = gen 
 >>> a 
 0 
 >>> b 
 1 
 >>> c 
 4 
 >>> # Unpacking dictionaries (keys, values, and items) 
 >>> my_dict = {'one': 1, 'two':2, 'three': 3} 
 >>> a, b, c = my_dict # Unpack keys 
 >>> a 
 'one' 
 >>> b 
 'two' 
 >>> c 
 'three' 
 >>> a, b, c = my_dict.values() # Unpack values 
 >>> a 
 1 
 >>> b 
 2 
 >>> c 
 3 
 >>> a, b, c = my_dict.items() # Unpacking key-value pairs 
 >>> a 
 ('one', 1) 
 >>> b 
 ('two', 2) 
 >>> c 
 ('three', 3) 

Когда дело доходит до распаковки в Python, мы можем использовать любую
итерацию справа от оператора присваивания. Левая часть может быть
заполнена tuple или list переменных. Посмотрите следующий пример, в
котором мы используем tuple в правой части оператора присваивания:

 >>> [a, b, c] = 1, 2, 3 
 >>> a 
 1 
 >>> b 
 2 
 >>> c 
 3 

Это работает точно так же, если мы используем итератор range()

 >>> x, y, z = range(3) 
 >>> x 
 0 
 >>> y 
 1 
 >>> z 
 2 

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

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

 >>> a, b, c = {'a', 'b', 'c'} 
 >>> a 
 'c' 
 >>> b 
 'b' 
 >>> c 
 'a' 

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

Упаковка с оператором *

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

 >>> *a, = 1, 2 
 >>> a 
 [1, 2] 

Чтобы этот код работал, левая часть присваивания должна быть tuple
(или list ). Вот почему мы используем конечную запятую. Этот tuple
может содержать столько переменных, сколько нам нужно. Однако он может
содержать только одно помеченное звездочкой выражение .

Мы можем сформировать начальное выражение, используя оператор распаковки
* вместе с действительным идентификатором Python, как *a в
приведенном выше коде. Остальные переменные в левом tuple называются
обязательными переменными, потому что они должны быть заполнены
конкретными значениями, иначе мы получим ошибку. Вот как это работает на
практике.

Упаковка конечных значений в b :

 >>> a, *b = 1, 2, 3 
 >>> a 
 1 
 >>> b 
 [2, 3] 

Упаковка начальных значений в : a

 >>> *a, b = 1, 2, 3 
 >>> a 
 [1, 2] 
 >>> b 
 3 

Упаковка одного значения в a потому что b и c являются
обязательными:

 >>> *a, b, c = 1, 2, 3 
 >>> a 
 [1] 
 >>> b 
 2 
 >>> c 
 3 

Не упаковывать значения в a ( a умолчанию — [] ), потому что b ,
c и d являются обязательными:

 >>> *a, b, c, d = 1, 2, 3 
 >>> a 
 [] 
 >>> b 
 1 
 >>> c 
 2 
 >>> d 
 3 

Отсутствует значение обязательной переменной ( e ), поэтому возникает
ошибка:

 >>> *a, b, c, d, e = 1, 2, 3 
 ... 
 ValueError: not enough values to unpack (expected at least 4, got 3) 

Упаковка значений в переменную с помощью * может быть удобной, когда
нам нужно собрать элементы генератора в одну переменную без
использования функции list() . В следующих примерах мы используем *
для упаковки элементов выражения
генератора и
объекта
диапазона в
отдельную переменную:

 >>> gen = (2 ** x for x in range(10)) 
 >>> gen 
 <generator object <genexpr> at 0x7f44613ebcf0> 
 >>> *g, = gen 
 >>> g 
 [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] 
 >>> ran = range(10) 
 >>> *r, = ran 
 >>> r 
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

В этих примерах * оператор упаковывает элементы в gen , и ran во
g и r соответственно. Благодаря его синтаксису мы избегаем
необходимости вызывать list() для создания list значений из range
, выражения генератора или функции генератора.

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

 >>> *r = range(10) 
 File "<input>", line 1 
 SyntaxError: starred assignment target must be in a list or tuple 

Если мы попытаемся использовать * для упаковки нескольких значений в
одну переменную, тогда нам потребуется использовать синтаксис tuple
Например, чтобы приведенный выше пример работал, нам просто нужно
добавить запятую после переменной r , как в *r, = range(10) .

Использование упаковки и распаковки на практике

Операции по упаковке и распаковке могут оказаться весьма полезными на
практике. Они могут сделать ваш код понятным, читаемым и питоническим.
Давайте рассмотрим некоторые распространенные варианты использования
упаковки и распаковки в Python.

Назначение параллельно

Один из наиболее распространенных вариантов использования распаковки в
Python — это то, что мы можем назвать параллельным присваиванием .
Параллельное присваивание позволяет вам присваивать значения в итерации
tuple (или list ) переменных в одном элегантном операторе.

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

 >>> employee = ["John Doe", "40", "Software Engineer"] 
 >>> name = employee[0] 
 >>> age = employee[1] 
 >>> job = employee[2] 
 >>> name 
 'John Doe' 
 >>> age 
 '40' 
 >>> job 
 'Software Engineer' 

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

 >>> name, age, job = ["John Doe", "40", "Software Engineer"] 
 >>> name 
 'John Doe' 
 >>> age 
 40 
 >>> job 
 'Software Engineer' 

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

Обмен значениями между переменными

Еще одно элегантное применение распаковки в Python — это обмен
значениями между переменными без использования временной или
вспомогательной переменной. Например, предположим, что нам нужно
поменять местами значения двух переменных a и b . Для этого мы можем
придерживаться традиционного решения и использовать временную переменную
для хранения значения, которое будет заменено следующим образом:

 >>> a = 100 
 >>> b = 200 
 >>> temp = a 
 >>> a = b 
 >>> b = temp 
 >>> a 
 200 
 >>> b 
 100 

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

 >>> a = 100 
 >>> b = 200 
 >>> a, b = b, a 
 >>> a 
 200 
 >>> b 
 100 

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

Сбор нескольких значений с помощью *

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

 >>> seq = [1, 2, 3, 4] 
 >>> first, body, last = seq[0], seq[1:3], seq[-1] 
 >>> first, body, last 
 (1, [2, 3], 4) 
 >>> first 
 1 
 >>> body 
 [2, 3] 
 >>> last 
 4 

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

 >>> seq = [1, 2, 3, 4] 
 >>> first, *body, last = seq 
 >>> first, body, last 
 (1, [2, 3], 4) 
 >>> first 
 1 
 >>> body 
 [2, 3] 
 >>> last 
 4 

Здесь волшебство first, *body, last = seq Оператор итеративной
распаковки * собирает элементы в середине seq в body . Это делает
наш код более читабельным, поддерживаемым и гибким. Вы можете подумать,
а почему более гибкие? Что ж, предположим, что seq меняет свою длину в
дороге, и вам все еще нужно собрать средние элементы в body . В этом
случае, поскольку мы используем распаковку в Python, для работы нашего
кода никаких изменений не требуется. Посмотрите этот пример:

 >>> seq = [1, 2, 3, 4, 5, 6] 
 >>> first, *body, last = seq 
 >>> first, body, last 
 (1, [2, 3, 4, 5], 6) 

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

Использование * для упаковки нескольких значений в одну переменную
может применяться в различных конфигурациях при условии, что Python
может однозначно определять, какой элемент (или элементы) назначить
каждой переменной. Взгляните на следующие примеры:

 >>> *head, a, b = range(5) 
 >>> head, a, b 
 ([0, 1, 2], 3, 4) 
 >>> a, *body, b = range(5) 
 >>> a, body, b 
 (0, [1, 2, 3], 4) 
 >>> a, b, *tail = range(5) 
 >>> a, b, tail 
 (0, 1, [2, 3, 4]) 

Мы можем переместить оператор * tuple (или list ) переменных,
чтобы собрать значения в соответствии с нашими потребностями.
Единственное условие — Python может определять, какой переменной
присвоить каждое значение.

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

 >>> *a, *b = range(5) 
 File "<input>", line 1 
 SyntaxError: two starred expressions in assignment 

Если мы используем два или более * в выражении присваивания, то мы
получим SyntaxError сообщающее нам, что найдено выражение, помеченное
двумя звездами. Это так, потому что Python не может однозначно
определить, какое значение (или значения) мы хотим присвоить каждой
переменной.

Удаление ненужных значений с помощью *

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

 >>> a, b, *_ = 1, 2, 0, 0, 0, 0 
 >>> a 
 1 
 >>> b 
 2 
 >>> _ 
 [0, 0, 0, 0] 

В качестве более наглядного примера этого варианта использования
предположим, что мы разрабатываем сценарий, который должен определять
используемую версию Python. Для этого мы можем использовать атрибут
sys.version_info
. Этот атрибут возвращает кортеж , содержащий пять компонентов номера
версии: major , minor , micro , releaselevel и serial . Но нам
нужны только major , minor и micro чтобы наш скрипт работал, так
что мы можем отказаться от остальных. Вот пример:

 >>> import sys 
 >>> sys.version_info 
 sys.version_info(major=3, minor=8, micro=1, releaselevel='final', serial=0) 
 >>> mayor, minor, micro, *_ = sys.version_info 
 >>> mayor, minor, micro 
 (3, 8, 1) 

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

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

Возврат кортежей в функциях

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

Посмотрите следующий пример, в котором мы определяем функцию для
вычисления квадрата и куба заданного числа:

 >>> def powers(number): 
 ... return number, number ** 2, number ** 3 
 ... 
 >>> # Packing returned values in a tuple 
 >>> result = powers(2) 
 >>> result 
 (2, 4, 8) 
 >>> # Unpacking returned values to multiple variables 
 >>> number, square, cube = powers(2) 
 >>> number 
 2 
 >>> square 
 4 
 >>> cube 
 8 
 >>> *_, cube = powers(2) 
 >>> cube 
 8 

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

Слияние итераций с оператором *

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

 >>> my_tuple = (1, 2, 3) 
 >>> (0, *my_tuple, 4) 
 (0, 1, 2, 3, 4) 
 >>> my_list = [1, 2, 3] 
 >>> [0, *my_list, 4] 
 [0, 1, 2, 3, 4] 
 >>> my_set = {1, 2, 3} 
 >>> {0, *my_set, 4} 
 {0, 1, 2, 3, 4} 
 >>> [*my_set, *my_list, *my_tuple, *range(1, 4)] 
 [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] 
 >>> my_str = "123" 
 >>> [*my_set, *my_list, *my_tuple, *range(1, 4), *my_str] 
 [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, '1', '2', '3'] 

Мы можем использовать итеративный оператор распаковки * при
определении последовательностей, чтобы распаковать элементы
подпоследовательности (или итерируемой) в конечную последовательность.
Это позволит нам создавать последовательности на лету из других
существующих последовательностей без вызова таких методов, как
append() , insert() и т. Д.

Последние два примера показывают, что это также более удобный и
эффективный способ объединения итераций. Вместо записи
list(my_set) + my_list + list(my_tuple) + list(range(1, 4)) + list(my_str)
мы просто пишем [*my_set, *my_list, *my_tuple, *range(1, 4), *my_str]
.

Распаковка словарей с помощью ** Оператора

В контексте распаковки в Python оператор ** называется оператором
распаковки
словаря
. Использование этого оператора было расширено в PEP
448 . Теперь мы можем
использовать его в вызовах функций, в интерпретациях и выражениях
генератора, а также в
отображениях
.

Базовый вариант использования оператора распаковки словарей — объединить
несколько словарей в один окончательный
словарь с одним выражением. Посмотрим, как это работает:

 >>> numbers = {"one": 1, "two": 2, "three": 3} 
 >>> letters = {"a": "A", "b": "B", "c": "C"} 
 >>> combination = {**numbers, **letters} 
 >>> combination 
 {'one': 1, 'two': 2, 'three': 3, 'a': 'A', 'b': 'B', 'c': 'C'} 

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

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

 >>> letters = {"a": "A", "b": "B", "c": "C"} 
 >>> vowels = {"a": "a", "e": "e", "i": "i", "o": "o", "u": "u"} 
 >>> {**letters, **vowels} 
 {'a': 'a', 'b': 'B', 'c': 'C', 'e': 'e', 'i': 'i', 'o': 'o', 'u': 'u'} 

Поскольку a присутствует в обоих словарях, преобладающее значение
исходит от vowels , то есть самого правого словаря. Это происходит
потому, что Python начинает добавлять пары ключ-значение слева направо.
Если в процессе Python находит ключи, которые уже вышли, интерпретатор
обновляет эти ключи новым значением. Вот почему в приведенном выше
примере a

Распаковка в For-Loops

Мы также можем использовать итеративную распаковку в контексте циклов
for Когда мы запускаем for , цикл назначает один элемент своей
итерации целевой переменной на каждой итерации. Если присваиваемый
элемент является итерируемым, то мы можем использовать tuple целевых
переменных. Цикл распакует итерацию под рукой в tuple целевых
переменных.

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

Продукт Цена Проданные единицы


Карандаш 0,25 1500
Ноутбук 1,30 550
Ластик 0,75 1000
… … …

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

 >>> sales = [("Pencil", 0.22, 1500), ("Notebook", 1.30, 550), ("Eraser", 0.75, 1000)] 
 >>> for item in sales: 
 ... print(f"Income for {item[0]} is: {item[1] * item[2]}") 
 ... 
 Income for Pencil is: 330.0 
 Income for Notebook is: 715.0 
 Income for Eraser is: 750.0 

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

Давайте посмотрим на альтернативную реализацию с использованием
распаковки в Python:

 >>> for product, price, sold_units in sales: 
 ... print(f"Income for {product} is: {price * sold_units}") 
 ... 
 Income for Pencil is: 330.0 
 Income for Notebook is: 715.0 
 Income for Eraser is: 750.0 

Теперь мы используем итеративную распаковку в нашем цикле for Это
делает наш код более читабельным и поддерживаемым, поскольку мы
используем описательные имена для идентификации элементов каждого
tuple . Это крошечное изменение позволит новичку-разработчику быстро
понять логику кода.

Также можно использовать оператор * for чтобы упаковать несколько
элементов в одну целевую переменную:

 >>> for first, *rest in [(1, 2, 3), (4, 5, 6, 7)]: 
 ... print("First:", first) 
 ... print("Rest:", rest) 
 ... 
 First: 1 
 Rest: [2, 3] 
 First: 4 
 Rest: [5, 6, 7] 

В этом for цикла, мы ловим первый элемент каждой последовательности в
first . Затем оператор * list значений в своей целевой переменной
rest .

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

 >>> data = [((1, 2), 2), ((2, 3), 3)] 
 >>> for (a, b), c in data: 
 ... print(a, b, c) 
 ... 
 1 2 2 
 2 3 3 
 >>> for a, b, c in data: 
 ... print(a, b, c) 
 ... 
 Traceback (most recent call last): 
 ... 
 ValueError: not enough values to unpack (expected 3, got 2) 

В первом цикле структура целевых переменных (a, b), c согласуется со
структурой элементов в итерации ((1, 2), 2) . В этом случае цикл
работает должным образом. Напротив, второй цикл использует структуру
целевых переменных, которые не согласуются со структурой элементов в
итерируемом объекте, поэтому цикл завершается ошибкой и вызывает
ValueError .

Упаковка и распаковка в функциях

Мы также можем использовать функции упаковки и распаковки Python при
определении и вызове функций. Это довольно полезный и популярный вариант
упаковки и распаковки в Python.

В этом разделе мы рассмотрим основы использования упаковки и распаковки
в функциях Python либо в определении функции, либо в ее вызове.

Примечание. Для получения более глубокого и подробного материала по
этим темам ознакомьтесь с аргументами переменной длины в Python с
*args и
**kwargs
.

Определение функций с помощью * и **

Мы можем использовать * и ** в сигнатуре функций Python. Это
позволит нам вызывать функцию с переменным количеством позиционных
аргументов ( * ) или с переменным количеством аргументов ключевого
слова, или с обоими. Рассмотрим следующую функцию:

 >>> def func(required, *args, **kwargs): 
 ... print(required) 
 ... print(args) 
 ... print(kwargs) 
 ... 
 >>> func("Welcome to...", 1, 2, 3, site='StackAbuse.com') 
 Welcome to... 
 (1, 2, 3) 
 {'site': 'StackAbuse.com'} 

Для указанной выше функции требуется по крайней мере один аргумент с
именем required . Он также может принимать переменное количество
позиционных и ключевых аргументов. В этом случае * собирает или
упаковывает дополнительные позиционные аргументы в кортеж с именем
args а ** собирает или упаковывает дополнительные аргументы
ключевого слова в словарь с именем kwargs . Оба, args и kwargs ,
являются необязательными и автоматически устанавливаются по умолчанию в
() и {} соответственно.

Несмотря на то, что имена args и kwargs широко используются
сообществом Python, они не являются обязательными для работы этих
методов. Синтаксис просто требует * или ** за которым следует
действительный идентификатор. Итак, если вы можете дать этим аргументам
осмысленные имена, то сделайте это. Это, безусловно, улучшит читаемость
вашего кода.

Вызов функций с помощью * и **

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

Вот простой пример того, как это работает:

 >>> def func(welcome, to, site): 
 ... print(welcome, to, site) 
 ... 
 >>> func(*["Welcome", "to"], **{"site": 'StackAbuse.com'}) 
 Welcome to StackAbuse.com 

Здесь * распаковывает последовательности вроде ["Welcome", "to"] в
позиционные аргументы. Аналогичным образом ** распаковывает словари в
аргументы, имена которых соответствуют ключам распакованного словаря.

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

 >>> def func(required, *args, **kwargs): 
 ... print(required) 
 ... print(args) 
 ... print(kwargs) 
 ... 
 >>> func("Welcome to...", *(1, 2, 3), **{"site": 'StackAbuse.com'}) 
 Welcome to... 
 (1, 2, 3) 
 {'site': 'StackAbuse.com'} 

Использование * и ** при определении и вызове функций Python
предоставит им дополнительные возможности и сделает их более гибкими и
мощными.

Заключение

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

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

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

import cv2
import numpy as np
import math

def distance(x1, y1, x2, y2):
«»»
Calculate distance between two points
«»»
dist = math.sqrt(math.fabs(x2-x1)**2 + math.fabs(y2-y1)**2)
return dist

def find_color1(frame):
«»»
Filter «frame» for HSV bounds for color1 (inplace, modifies frame) & return coordinates of the object with that color
«»»
hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
hsv_lowerbound = np.array([102, 152, 0]) #replace THIS LINE w/ your hsv lowerb
hsv_upperbound = np.array([118, 255, 255])#replace THIS LINE w/ your hsv upperb
mask = cv2.inRange(hsv_frame, hsv_lowerbound, hsv_upperbound)
res = cv2.bitwise_and(frame, frame, mask=mask) #filter inplace
, cnts, = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(cnts) > 0:
maxcontour = max(cnts, key=cv2.contourArea)

    #Find center of the contour 
    M = cv2.moments(maxcontour)
    if M['m00'] > 0 and cv2.contourArea(maxcontour) > 1000:
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01']/M['m00'])
        return (cx, cy), True
    else:
        return (700, 700), False #faraway point
else:
    return (700, 700), False #faraway point

def find_color2(frame):
«»»
Filter «frame» for HSV bounds for color1 (inplace, modifies frame) & return coordinates of the object with that color
«»»
hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
hsv_lowerbound = np.array([40, 83, 0])#replace THIS LINE w/ your hsv lowerb
hsv_upperbound = np.array([101, 255, 255])#replace THIS LINE w/ your hsv upperb
mask = cv2.inRange(hsv_frame, hsv_lowerbound, hsv_upperbound)
res = cv2.bitwise_and(frame, frame, mask=mask)
,cnts, = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(cnts) > 0:
maxcontour = max(cnts, key=cv2.contourArea)

    #Find center of the contour 
    M = cv2.moments(maxcontour)
    if M['m00'] > 0 and cv2.contourArea(maxcontour) > 2000:
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01']/M['m00'])
        return (cx, cy), True #True
    else:
        return (700, 700), True #faraway point
else:
    return (700, 700), True #faraway point

cap = cv2.VideoCapture(0)

while(1):
_, orig_frame = cap.read()

if orig_frame is None:
    break


#we'll be inplace modifying frames, so save a copy
copy_frame = orig_frame.copy() 
(color1_x, color1_y), found_color1 = find_color1(copy_frame)
(color2_x, color2_y), found_color2 = find_color2(copy_frame)

#draw circles around these objects
cv2.circle(copy_frame, (color1_x, color1_y), 20, (255, 0, 0), -1)
cv2.circle(copy_frame, (color2_x, color2_y), 20, (0, 128, 255), -1)

if found_color1 and found_color2:
    #trig stuff to get the line
    hypotenuse = distance(color1_x, color1_x, color2_x, color2_y)
    horizontal = distance(color1_x, color1_y, color2_x, color1_y)
    vertical = distance(color2_x, color2_y, color2_x, color1_y)
    angle = np.arcsin(vertical/hypotenuse)*180.0/math.pi

    #draw all 3 lines
    cv2.line(copy_frame, (color1_x, color1_y), (color2_x, color2_y), (0, 0, 255), 2)
    cv2.line(copy_frame, (color1_x, color1_y), (color2_x, color1_y), (0, 0, 255), 2)
    cv2.line(copy_frame, (color2_x, color2_y), (color2_x, color1_y), (0, 0, 255), 2)

    #put angle text (allow for calculations upto 180 degrees)
    angle_text = ""
    if color2_y < color1_y and color2_x > color1_x:
        angle_text = str(int(angle))
    elif color2_y < color1_y and color2_x < color1_x:
        angle_text = str(int(180 - angle))
    elif color2_y > color1_y and color2_x < color1_x:
        angle_text = str(int(180 + angle))
    elif color2_y > color1_y and color2_x > color1_x:
        angle_text = str(int(360 - angle))
    
    #CHANGE FONT HERE
    cv2.putText(copy_frame, angle_text, (color1_x-30, color1_y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 128, 229), 2)

cv2.imshow('AngleCalc', copy_frame)
cv2.waitKey(5) 

cap.release()
cv2.destroyAllWindows()

error

Traceback (most recent call last):
File «C:/Users/Besitzer/Real-Time-and-Static-Angles-Calculation-main/Real-Time-and-Static-Angles-Calculation-main/Angle_Findings Taha/color_based.py», line 72, in
(color1_x, color1_y), found_color1 = find_color1(copy_frame)
File «C:/Users/Besitzer/Real-Time-and-Static-Angles-Calculation-main/Real-Time-and-Static-Angles-Calculation-main/Angle_Findings Taha/color_based.py», line 21, in find_color1
, cnts, = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ValueError: not enough values to unpack (expected 3, got 2)
[ WARN:1@4.056] global D:aopencv-pythonopencv-pythonopencvmodulesvideoiosrccap_msmf.cpp (539) `anonymous-namespace’::SourceReaderCB::~SourceReaderCB terminating async callback

Process finished with exit code 1

Понравилась статья? Поделить с друзьями:
  • Valorant ошибка val 1067
  • Valorant ошибка riot vanguard
  • Valorant ошибка 128 как решить
  • Valorant не запускается ошибка couldn t start
  • Valorant win64 shipping exe ошибка