I'm trying to move a usage of itertools.product
inside a function. When I try to do this, I am presented with the following error message and I'm not sure why:
TypeError: 'int' object is not iterable
The code is as follows. In the main
function, you can see the algorithm used outside the function and then you can see the algorithm used when packaged in the function:
#!/usr/bin/env python
import itertools
def main():
elements_specification = [[10, 20], [30, 40], [50, 60]]
lists = [list(list_generated) for index, element_specification in enumerate(elements_specification) for list_generated in itertools.product(*elements_specification[:index + 1])]
for list_configuration in lists:
print(list_configuration)
print("---")
for list_configuration in list_element_combinations_variadic(
[[10, 20], [30, 40], [50, 60]]
):
print(list_configuration)
def list_element_combinations_variadic(
elements_specification
):
"""
This function accepts a specification of lists of elements for each place in
lists in the form of a list, the elements of which are lists of possible
elements and returns a list of lists corresponding to the combinations of
elements of the specification with varying numbers of elements.
For example, the list elements specification [[10, 20], [30, 40], [50, 60]]
yields the following lists:
[10]
[20]
[10, 30]
[10, 40]
[20, 30]
[20, 40]
[10, 30, 50]
[10, 30, 60]
[10, 40, 50]
[10, 40, 60]
[20, 30, 50]
[20, 30, 60]
[20, 40, 50]
[20, 40, 60]
"""
lists = [list(list_generated) for index, elements_specification in enumerate(elements_specification) for list_generated in itertools.product(*elements_specification[:index + 1])]
return lists
if __name__ == "__main__":
main()
Basically, you have a typo between the main
method and the other one.
In main
, you correctly have element_specification
in the for
for index, element_specification in enumerate(elements_specification)
But in the other method you have elements_specification
in the for
for index, elements_specification in enumerate(elements_specification)
Which just so happens to be the name of the parameter for that method, so you're reassigning that parameter in your list-comprehension
Try this instead
lists = [list(list_generated) for index, element in enumerate(elements_specification) for list_generated in itertools.product(*elements_specification[:index + 1])]
return lists
Or since you don't even need the element
from the enumerate
, just use range
.
lists = [list(list_generated) for index in range(len(elements_specification)) for list_generated in itertools.product(*elements_specification[:index + 1])]
return lists