products module
Simple function for building ensembles of iterators that represent disjoint partitions of an overall Cartesian product.
- products.products.products(*collections, number=None)[source]
Accept zero or more
Collection
instances as arguments and return aSequence
of the specified number of disjoint subsets of the Cartesian product of the suppliedCollection
instances. Each subset is represented as anIterable
and the union of the disjoint subsets is equal to the overall Cartesian product.- Parameters
collections (
Tuple
[Collection
, …]) – Zero or more arguments that represent the factor sets of the Cartesian product.number (
Optional
[int
]) – Number of disjoint subsets to return.
>>> ss = products(range(1, 3), {'a', 'b'}, (False, True), number=3) >>> for s in sorted([sorted(list(s)) for s in ss]): ... for t in s: ... print(t) (1, 'a', False) (1, 'a', True) (1, 'b', False) (1, 'b', True) (2, 'a', False) (2, 'a', True) (2, 'b', False) (2, 'b', True)
Two additional basic examples are presented below.
>>> (x, y, z) = ([1, 2], ['a', 'b'], [True, False]) >>> [list(s) for s in products(x, y, number=2)] [[(1, 'a'), (1, 'b')], [(2, 'a'), (2, 'b')]] >>> for s in [list(s) for s in products(x, y, z, number=2)]: ... print(s) [(1, 'a', True), (1, 'a', False), (1, 'b', True), (1, 'b', False)] [(2, 'a', True), (2, 'a', False), (2, 'b', True), (2, 'b', False)]
By default (if the
number
argument is not assigned a value), the number of disjoint subsets is one. Note that the union of the disjoint subsets is equivalent to the output of theitertools.product
function.>>> p = itertools.product([1, 2], {'a', 'b'}, (True, False)) >>> ss = products([1, 2], {'a', 'b'}, (True, False)) >>> list(p) == list(list(ss)[0]) True
If no sets are specified, the Cartesian product consists of a single empty tuple. If there is one set, the Cartesian product consists of a set of one-element tuples. In both cases, a list of disjoint subsets is returned as in all other cases (even though the number of disjoint subsets may be one).
>>> list(list(products())[0]) [()] >>> list(list(products([1, 2]))[0]) [(1,), (2,)]
It is possible to confirm that the returned subsets are disjoint, and that the union of the disjoint subsets is the Cartesian product.
>>> (x, y, z) = ([1, 2], ['a', 'b'], [True, False]) >>> ss = [set(s) for s in products(x, y, z, x, y, z, number=5)] >>> set([len(ss[i] & ss[j]) for i in range(5) for j in range(5) if i != j]) {0} >>> s = ss[0] | ss[1] | ss[2] | ss[3] | ss[4] >>> s == set(itertools.product(x, y, z, x, y, z)) True >>> len(products(*[[1, 2, 3]]*1000, number=5)) 5 >>> ls = [len(products(*[[1, 2]]*1000, number=n)) for n in range(1, 100)] >>> ls == list(range(1, 100)) True
If the requested number of disjoint subsets exceeds the number of elements in Cartesian product, the number of disjoint subsets will be equivalent to the number of elements in the Cartesian product.
>>> len(products([1, 2], ['a', 'b'], number=10)) 4
Any attempt to apply this function to arguments that have unsupported types raises an exception.
>>> products([1, 2], number='abc') Traceback (most recent call last): ... TypeError: number of disjoint subsets must be an integer >>> products((i for i in range(3)), number=2) Traceback (most recent call last): ... TypeError: arguments must be collections >>> products([1, 2], number=0) Traceback (most recent call last): ... ValueError: number of disjoint subsets must be a positive integer >>> products([1, 2], number=0) Traceback (most recent call last): ... ValueError: number of disjoint subsets must be a positive integer