The itertools module provides a number of useful functions for manipulating collections of elements through iterators.

The combinations_with_replacement() function returns the combinations of the given iterable with replacement allowed, meaning that the same element can appear multiple times in the same combination. This is in contrast to the combinations() function, which only includes each element from the iterable once.

Syntax:
combinations_with_replacement(iterable, r)
copy
iterable Required. The iterable whose combinations we want.
r Required.  Indicates the length of of each of the combinations to be returned.
Parameters:

The function returns an iterator of successive r-length tuples where each tuple represents a possible r-length combination of the input iterable.

ExampleEdit & Run
from itertools import combinations_with_replacement


data = ['A', 'B', 'C']

for i in combinations_with_replacement(data, 3):
    print(i)
copy
Output:
('A', 'A', 'A') ('A', 'A', 'B') ('A', 'A', 'C') ('A', 'B', 'B') ('A', 'B', 'C') ('A', 'C', 'C') ('B', 'B', 'B') ('B', 'B', 'C') ('B', 'C', 'C') ('C', 'C', 'C') [Finished in 0.010909256525337696s]

In the following example we use nested for loops to get  a list of all the possible combinations.

ExampleEdit & Run
from itertools import combinations_with_replacement


data = ['A', 'B', 'C']

combs = []
for i in  range(len(data)):
    for comb in combinations_with_replacement(data, i + 1):
        combs.append(comb)

print(*combs, sep = '\n')
copy
Output:
('A',) ('B',) ('C',) ('A', 'A') ('A', 'B') ('A', 'C') ('B', 'B') ('B', 'C') ('C', 'C') ('A', 'A', 'A') ('A', 'A', 'B') ('A', 'A', 'C') ('A', 'B', 'B') ('A', 'B', 'C') ('A', 'C', 'C') ('B', 'B', 'B') ('B', 'B', 'C') ('B', 'C', 'C') ('C', 'C', 'C') [Finished in 0.010625905357301235s]