A tuple is a collection of multiple items in an ordered manner. Tuples are sequences denoted by parenthesis () and placing the items within parentheses, separated by commas. The items stored inside a tuple can be of different types such as integer, string, float, list, etc. The main characteristic of a tuple is that it is immutable. Once a tuple has been assigned values, we cannot modify it. We can reassign new values to a tuple but cannot change its individual items. Tuple comprehension cannot be directly performed in python, but there are other alternatives to it.
What is comprehension in Python?
In python, comprehension is a technique with the help of which we can create sequences of elements in a short, concise manner. Moreover, comprehension enables us to create a compact code to create new sequences from already existing sequences. The sequences can be lists, dictionaries, sets, etc.
The syntax of a list comprehension is:
output_list = [item for item in existing_list if (condition to be satisfied) ]
Here if we observe, the comprehension consists of three parts – the item to be included in the output_list, the for loop, and the if condition.
Let us understand comprehension by an example.
Suppose we have a list containing some numbers, and we want to create a new list with multiples of 5. The traditional way of doing that would be iterating over a for loop.
list1 = [10,6,45,89,90,1,225,76]
list2 = []
for i in list1:
if i % 5 == 0:
list2.append(i)
print(list2)
Output:
[10, 45, 90, 225]
Instead of this method, we can simplify the above code by performing comprehension.
list1 = [10,6,45,89,90,1,225,76]
list2 = [i for i in list1 if i%5 == 0]
print(list2)
Output:
[10, 45, 90, 225]
As you can see here, applying comprehension halved the number of lines of code form 6 to 3.
Why tuple comprehension is not possible?
We can perform comprehension to sequences such as lists, sets, dictionaries but not to tuples. For example, if we want to perform list comprehension, we use square brackets [ ]. We use curly braces { }, but we would have to use parentheses for the tuple for dictionary comprehension. But we already use parentheses for generator comprehension. Also, since tuples are immutable, tuple comprehension becomes very complex and limited.
Example: Let us take a tuple consisting of numbers.
tuple1 = (10,6,45,89,90,1,225,76)
Now, we shall try to perform tuple comprehension for a new tuple containing multiples of 5.
tuple2 = (i for i in tuple1 if i%5 == 0)
print(tuple2)
When we execute the above code and try to print tuple2, we get a generator object as an output.
<generator object <genexpr> at 0x7f8a7c06c4d0>
A tuple comprehension is considered to be less fundamental than a list comprehension. So there is no special syntax dedicated for the same. Yet, if you want a tuple after applying comprehension, it can be achieved by wrapping a tuple around a generator object.
Wrap generator object using tuple() function
Wrapping around the generator object is achieved by explicitly casting using the built-in tuple method. Let us consider the same example as mentioned above.
tuple1 = (10,6,45,89,90,1,225,76)
Now, applying this code (i for i in tuple1 if i%5 == 0)
would create a generator object. So, to convert into a type tuple, we shall use the tuple() function.
tuple2 = tuple((i for i in tuple1 if i%5 == 0))
print(tuple2)
This will print a tuple containing multiples of 5.
(10, 45, 90, 225)
You can also check the type of tuple2. It will show that it belongs to the tuple class.
print(type(tuple2))
The output is:
<class 'tuple'>
Wrap tuple() function around list comprehension
Another way of wrapping tuple() function to perform list comprehension first and then convert it into a tuple.
tuple1 = (10,6,45,89,90,1,225,76)
tuple2 = tuple([i for i in tuple1 if i%5 == 0])
Here, we store the output of the comprehension into a list and then explicitly convert it into a tuple.
Printing tuple2 and its type:
print(tuple2)
print(type(tuple2))
Output:
(10, 45, 90, 225)
<class 'tuple'>
Wrapping using a trailing comma and an asterisk.
Using a trailing comma with an asterisk(*) is another way of creating a tuple. Here, the asterisk symbolizes the tuple() function. Not using the asterisk and only using the trailing comma will create a tuple. But the contents of that tuple would be the generator object.
tuple1 = (10,6,45,89,90,1,225,76)
tuple2 = (i for i in tuple1 if i%5 == 0),
When we execute the above code, the type of tuple2 would be a tuple.
print(type(tuple2))
Output:
<class 'tuple'>
But, if we try to print tuple2, it will print the generator object.
print(tuple2)
Output:
(<generator object <genexpr> at 0x7f8a7c06c5d0>,)
So, we shall add the asterisk before the parentheses to store the tuple elements.
tuple1 = (10,6,45,89,90,1,225,76)
tuple2 = *(i for i in tuple1 if i%5 == 0),
print(tuple2)
print(type(tuple2))
The output will be:
(10, 45, 90, 225)
<class 'tuple'>
Creating a list first and then converting it into a tuple is equivalent to using an asterisk before the comprehension.
To summarize, there is no syntax available for performing a tuple comprehension. But you can use the tuple() built-in function or the asterisk and wrap that around the generator object or list comprehension to create tuples out of comprehension.
Must Read
FAQ’s on tuple comprehension
Q. List comprehension vs tuple comprehension
A. List comprehension is straightforward to achieve by using square brackets before the comprehension. Whereas, as seen above, tuple comprehension cannot be achieved directly. Therefore, list comprehension is a way of achieving tuple comprehension.
Q. Generator comprehension vs list comprehension
A. The main difference between list and generator comprehension is that list comprehension generates an entire list and hence occupies more memory. Whereas generator comprehension generates an object which generates items only when required. So, generator comprehension occupies less memory.
Let us consider an example of both, list and generator comprehension.
import sys
list1 = [i for i in range(100)]
gen1 = (i for i in range(100))
print("List comprehension memory:",sys.getsizeof(list1))
print("Generator comprehension memory:",sys.getsizeof(gen1))
The output is:
List comprehension memory: 920
Generator comprehension memory: 128
As seen above, the generator occupies less memory than list comprehension as the latter will store complete list in memory.
That was all about tuple comprehension. If you have any ideas to share or any questions on mind, let us know in the comments below.