# Itertools in Python

## Overview

itertools is a module in python that provides us a collection of functions to handle iterators. itertools in python is a fast, memory-efficient module that utilizes the system's computational resources efficiently. Using this module enhances the readability and maintainability of the code.

## Introduction to Itertools Module in Python

An Iterator is an object that helps us in iterating over another python object. While an Iterable is basically a python object that can be iterated over.

In the above example, we created a list named l that contains values of different data types. These values can be printed by iterating over this list with the help of a for loop.

itertools is a module in python that provides us with a collection of functions to handle iterators. The itertools module needs to be imported before using it in the program.

We can import the module using the following statement.

## Types of iterators

Different types of iterators provided by this module are:

**Infinite iterators****Combinatoric iterators****Terminating iterators**

**1. Infinite iterators**

An Iterator in python is an object that can be used with a loop to traverse an iterable. Lists, sets, dictionaries, and tuples are some of the widely used iterators in python. It is not necessary that an iterator has to exhaust it can contain an infinite number of elements, such types of iterators are known as Infinite iterators.

count, cycle, and repeat are three types of infinite iterators in python.

**count(start, step)**This iterator prints value from*start*and continues infinitely. It takes an optional*step*argument, which if provided skips given the number of values. If these arguments are not provided, then by*default value of start is 0 and step is 1*.

**Example**

**Output**

In the above program, we iterate over a count iterator having start = 3 and step = 5. In the first iteration, the value of i is 3. In the next step, we add 5. Therefore the value of i is now 8. This would continue infinitely but, we have added a break when i == 33.

**cycle(iterable)**This iterator takes an iterable as an argument and prints it indefinitely in a cyclic manner.

**Example**

**Output**

In the above program, we created a list l. Usually, a for loop traverses over an iterable until it gets exhausted. Since this list had 2 items, the for loop would have iterated 2 times only. But in this case, we used the cycle() infinite iterator, in this when the list was exhausted we started over again from the beginning.

**repeat(object, times)**This iterator takes an object and repeats it infinitely. It takes an optional times parameter that is used as a termination condition.**Example**

**Output**

In the above program, we have created an iterator that just repeats scaler infinitely. But because we have also given it a times = 5 argument, we have limited the output to 5 times.

### 2. Combinatoric iterators

Permutations, Combinations, and Cartesian Products are some of the recursive generators also known as Combinatoric iterators used to simplify complex combinatorial constructs.

Product(), Permutations(), Combinations() and Combinations_with_replacement() are 4 Combinataric iterators.

**Product()**This iterator is used to compute the cartesian product of the input series of iterables. It takes an optional argument repeat, that specifies the number of repetitions for the product of an iterable with itself. The output is in the form of sorted tuples.

**Example**

**Output**

**Permutations(iterable, group_size)**This iterator is used to generate all the possible permutations of an iterable. Every element is decided to be unique based on its position and not its value. Permutations() takes iterable and group_size as two of its arguments, if the group_size value is not given or is None, then group_size takes the length of the iterable as its value.

**Example**

**Output**

**Combinations(iterable, group_size)**This iterator is used to generate all the possible unique combinations for the iterable passed as an argument along with the specified group_size in sorted order.

**Example**

**Output**

**Combinations_with_replacement(iterable, group_size)**This iterator is similar to combinations(), but this one allows individual elements in an iterable to get repeated more than once.

**Example**

**Output**

**3. Terminating iterators**

These types of iterators are used to work with small input sequences and produce output using the functionality implemented in the iterator.

There are different types of terminating iterators:

**accumulate(iterable, function)**

This finite iterator takes an iterable and a function as arguments, and the function is implemented at each iteration to return the accumulated result. *If no function is passed to the accumulate iterator, then the addition is done by default*.

**Example**

**Output**

In the first example, no function is passed, therefore successive addition is performed on the passed iterable. While in the second example, operator.mul takes two numbers and multiplies them successively to print the accumulated result.

**chain(iterable1, iterable2)**This finite iterator displays all the values passed as iterables in the form of a chain.

**Example**

**Output**

**chain.from_iterable(iterable1)**This finite iterator is implemented similar to chain() but here only an iterator container is passed instead of multiple.

**Example**

**Output**

**compress(iterable, selector)**This finite iterator filters the value from the passed iterable based on the boolean list passed as the second argument. Values corresponding to 1 or True are selected while the rest all are ignored.

**Example**

**Output**

**dropwhile(function, sequence)**This finite iterator removes the sequence elements as long as the passed function returns True, but once the function returns False all the remaining elements afterward are printed.

**Example**

**Output**

In the above program, dropwhile() instructs to drop each element while it is less than 4. Once it encounters an element that is not less than 4, it returns all remaining elements. That is why element 2 at last is also printed.

**filterfalse(function, sequence)**This finite iterator prints only those values for which the passed function returns False.

**Example**

**Output**

**islice(iterable, start, stop, step)**This finite iterator allows the user to slice the passed iterable based on the other three arguments start, stop, step.

**Example**

**Output**

The above program implements islice() to slice the passed list starting from the 0th element till the 6th skipping along with taking a step of 2.

**starmap(function, iterable)**This finite iterator computes the function value on the arguments of the passed iterable.

**Example**

**Output**

**takewhile(function, iterable)**This finite iterator is opposite to dropwhile(), as it prints those values from the iterable for which the passed function returns True till the function becomes false.

**Example**

**Output**

**tee(iterator, count)**This finite iterator splits the passed iterator into a count number of independent iterators. The default value of count is 2.

**Example**

**Output**

**zip_longest(*iterables, fillvalue)**This finite iterator prints the values by aggregating them from each iterable. If any iterable is fully exhausted, the remaining values are filled by the value given to the fillvalue parameter. The default value for fillvalue is None.

**Example**

**Output**

## List of All Functions in the itertools Module

Function | Description |
---|---|

count() | This iterator prints value from start and continues infinitely. |

cycle() | This iterator takes an iterable as an argument and prints it indefinitely in a cyclic manner. |

repeat() | This iterator takes an object and repeats it infinitely. |

product() | This iterator is used to compute the cartesian product of the input series of iterables. |

permutations() | This iterator is used to generate all the possible permutations of an iterable. Every element is decided to be unique based on its position and not its value. |

combinations() | This iterator is used to generate all the possible unique combinations for the iterable passed as an argument along with the specified group_size in sorted order. |

combinations_with_replacement() | This iterator is similar to combinations(), but this one allows individual elements in an iterable to get repeated more than once. |

accumulate() | This finite iterator takes an iterable and a function as arguments, and the function is implemented at each iteration to return the accumulated result. |

chain() | This finite iterator displays all the values passed as iterables in the form of a chain. |

chain.from_iterable() | This finite iterator is implemented similar to chain() but here only an iterator container is passed instead of multiple. |

compress() | This finite iterator filters the value from the passed iterable based on the boolean list passed as the second argument. |

dropwhile() | This finite iterator removes the sequence elements as long as the passed function returns True, but once the function returns False all the remaining elements afterward are printed. |

filterfalse() | This finite iterator prints only those values for which the passed function returns False. |

isslice() | This finite iterator allows the user to slice the passed iterable based on the other three arguments start, stop, step. |

starmap() | This finite iterator computes the function value on the arguments of the passed iterable. |

takewhile() | This finite iterator is opposite to dropwhile(), as it prints those values from the iterable for which the passed function returns True till the function becomes false. |

tee() | This finite iterator splits the passed iterator into the count number of independent iterators. |

zip_longest() | This finite iterator prints the values by aggregating them from each iterable. If any iterable is fully exhausted, the remaining values are filled by the value given to the fillvalue parameter. |

## Conclusion

- itertools module in python is a fast, memory-efficient module that utilizes the system's computational resources efficiently.
- Different types of iterators provided by this module are:
*Infinite iterators**Combinatoric iterators**Terminating iterators*

- An Iterator is a python object that helps us in iterating over another python object. While an Iterable is an object that can be iterated over.
- The itertools module needs to be imported before using it in the program.