
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Unpack Using Star Expression in Python
Introduction
One of the basic limitation of unpacking is that you must know the length of the sequences you are unpacking in advance.
How to do it..
random_numbers = [0, 1, 5, 9, 17, 12, 7, 10, 3, 2] random_numbers_descending = sorted(random_numbers, reverse=True) print(f"Output \n*** {random_numbers_descending}")
Output
*** [17, 12, 10, 9, 7, 5, 3, 2, 1, 0]
If I now wanted to find out the largest and second largest from the numbers, we will get an exception "too many values to unpack".
print(f"Output \n*** Getting the largest and second largest") largest, second_largest = random_numbers_descending
Output
*** Getting the largest and second largest
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) in 1 print(f"Output \n*** Getting the largest and second largest") ----> 2 largest, second_largest = random_numbers_descending ValueError: too many values to unpack (expected 2)
Python often rely on indexing and slicing. For example, when I want to extract the largest, second largest from a list of items below is how we can do.
largest = random_numbers_descending[0] print(f"Output \n*** Getting the largest - {largest}")
Output
*** Getting the largest - 17
second_largest = random_numbers_descending[1] print(f"Output \n*** Getting the second largest - {second_largest}")
Output
*** Getting the second largest - 12
rest_of_numbers = random_numbers_descending[2:] print(f"Output \n*** Getting the rest of numbers - {rest_of_numbers}")
Output
*** Getting the rest of numbers - [10, 9, 7, 5, 3, 2, 1, 0]
While this works, all of the indexing and slicing is visually noisy. In practice, it is error prone to divide the members of a sequence into various subsets this way.
To do it better, Python supports catch-all unpacking through a starred expression.
This starred syntax allows one part of the unpacking assignment to receive all values that do not match any other part of the unpacking pattern.
largest,second_largest, *rest_of_numbers = random_numbers_descending print(f"Output \n largest: {largest} \n second_largest:{second_largest} \n rest_of_numbers:{rest_of_numbers}")
Output
largest: 17 second_largest:12 rest_of_numbers:[10, 9, 7, 5, 3, 2, 1, 0]
How does the above code look? In a single line which is also easier to read we are able to acheive the output. A starred expression may appear in any position, so you can get the benefits of catch-all unpacking anytime you need to extract one slice
largest: 17 rest_of_numbers:[12, 10, 9, 7, 5, 3, 2, 1] smallest:0
*rest_of_numbers, second_smallest, smallest = random_numbers_descending print(f"Output \n rest_of_numbers:{rest_of_numbers} \n second_smallest: {second_smallest} \n smallest:{smallest}")
rest_of_numbers:[17, 12, 10, 9, 7, 5, 3, 2] second_smallest: 1 smallest:0
However, to unpack assignments that contain a starred expression, you must have at least one required part, or else you’ll get a SyntaxError. We can’t use a catch-all expression on its own.
*rest_of_numbers = random_numbers_descending
File "", line 1 *rest_of_numbers = random_numbers_descending ^ SyntaxError: starred assignment target must be in a list or tuple
We also cannot use multiple catch-all expressions in a single-level unpacking pattern. This is another important note to consider.
*rest_of_numbers, *more_smallest, smallest = random_numbers_descending
File "", line 1 *rest_of_numbers, *more_smallest, smallest = random_numbers_descending ^ SyntaxError: two starred expressions in assignment
But it is possible to use multiple starred expressions in an unpacking assignment statement, as long as they’re catch-alls for different parts of the multilevel structure being unpacked.
player_grandslame_and_atptitles = { 'Federer': (20, 103), 'Nadal': (20,84),} ((player1, (grandslam1, *atptitles1)), (player2, (grandslam2, *atptitles2))) = player_grandslame_and_atptitles.items() print(f'Output \nPlayer - {player1} Have acheived {grandslam1} grandslams and , {atptitles1} atp tour titles') print(f'Player - {player2} Have acheived {grandslam2} grandslams and , {atptitles2} atp tour titles')
Output
Player - Federer Have acheived 20 grandslams and , [103] atp tour titles Player - Nadal Have acheived 20 grandslams and , [84] atp tour titles
Starred expressions become list instances in all cases. If there are no leftover items from the sequence being unpacked, the catch-all part will be an empty list. This is especially useful when you are processing a sequence that you know in advance has at least N elements.
random_numbers = [0, 1] first, second, *rest = random_numbers print(f"Output \n{first, second, rest}")
Output
(0, 1, [])