Reputation: 353
I have two class instances which have list attributes, e.g.:
foo.range = [1,2]
bar.range = [3,4]
I also have a function which takes multiple arguments:
def permutations(*args):
return list(itertools.product(arg.range for arg in args))
I want permutations(foo, bar)
to return all permutations of those two (or more) lists (i.e. [(1,3), (1,4) …]
) but I actually get [([1, 2],), ([3, 4],)]
Could someone please help me to understand where am I going wrong and how to achieve the result I'm hoping for?
Upvotes: 0
Views: 82
Reputation: 251196
itertools.product
expects the iterables as individual arguments(itertools.product(*iterables[, repeat])
), so you need to unpack the items to it using the the splat(*
) operator:
>>> def permutations(*args):
return list(itertools.product(*(arg.range for arg in args)))
>>> permutations(foo, bar)
[(1, 3), (1, 4), (2, 3), (2, 4)]
Consider this simple function, it will collect all positional arguments passed to it in args:
>>> def func(*args):
print args
print list(args[0])
...
When we pass it a generator expression it is collected as one individual item in the args
tuple:
>>> func(x for x in range(5))
(<generator object <genexpr> at 0x7fda2ab4e780>,)
[0, 1, 2, 3, 4]
To fix this we need to unpack our generator expression, also as somethine like *x for x in range(5)
is not a valid syntax in Python, we need to add extra parenthesis around the generator expression:
>>> func(*(x for x in range(5)))
(0, 1, 2, 3, 4)
# Failed as expected for args[0]
Traceback (most recent call last):
File "<ipython-input-215-13af4340dad1>", line 1, in <module>
func(*(x for x in range(5)))
File "<ipython-input-213-08941e2a3c06>", line 3, in func
print list(args[0])
TypeError: 'int' object is not iterable
Upvotes: 2