1

I use itertools.product in its usual form to generate a list of tuples.

I then iterate through the list with a standard for i in myList: loop to generate desired results.

I then wish to iterate a second time through the same loop using for i in myList:, but it does not execute the second loop without me regenerating the myList prior to loop entry.

Why is this ?

I have looked at the itertools help in the python docs which gives an explanation of what itertools.product() does, but it does not explain why the user would need to invoke before each loop entry.

https://docs.python.org/2/library/itertools.html#itertools.product

import itertools as it


def loopsThings(*lsts):


    # list of possibilities
    allPossible = it.product(a, b, c)

    for i in allPossible:
        print('first pass', i)

    # list of possibilities
    # second pass works if this is un-commented !!
    # allPossible = it.product(a, b, c) 

    for i in allPossible:
        print('second pass', i)

    return


a = [3, 5, 10]
b = [1, 9, 15]
c = [4, 8]

loopsThings(a, b, c)

i expect to get 2 lists, but only get 1 list (first pass)

in order to get the second list i need to run allPossible = it.product(a, b, c) before entry of the second loop.

2 Answers2

4

itertools.product returns a <class 'itertools.product'>. You need to make a list of allPossible to get the expected result.

import itertools as it


def loopsThings(*lsts):


    # list of possibilities
    allPossible = list(it.product(a, b, c))

    for i in allPossible:
        print('first pass', i)

    # list of possibilities
    # second pass works if this is un-commented !!
    # allPossible = it.product(a, b, c) 

    for i in allPossible:
        print('second pass', i)

    return


a = [3, 5, 10]
b = [1, 9, 15]
c = [4, 8]

loopsThings(a, b, c)
ParthS007
  • 2,581
  • 1
  • 22
  • 37
  • Why can't you use the `` more than once? OP's question is `Why is this ?` – wwii Oct 12 '19 at 22:29
  • 1
    Some Python standard library functions like product return iterator objects that are only meant for a single-use iteration. Internally, they are like a pointer that points to an item in a linked list that moves up once every time a new item is fetched (through the next function). Converting to a list iterates through the iterator but stores all items in a “normal” list. – gerwin Oct 12 '19 at 22:34
  • Most functions that return iterators do so because they generate output on the fly, not because they're tracking position in some container that already has all the output. – user2357112 Oct 12 '19 at 22:44
  • Yes, that’s true. My comment doesn’t really cover that but can’t seem to edit it. – gerwin Oct 12 '19 at 22:48
2

Using the previous comments:

This is the answer:

Some Python standard library functions like product return iterator objects that are only meant for a single-use iteration. Internally, they are like a pointer that points to an item in a linked list that moves up once every time a new item is fetched (through the next function).

The solution is to change from a (single use) object allPossible = it.product(a, b, c) to a list (using list comprehension works) allPossible = [x for x in it.product(a, b, c)]