Reputation: 1718
I have a function on zero or more Pyomo sets:
def myfunc(*sets):
if len(sets) == 0:
return # Do something else that is irrelevant here
indices = reduce(lambda x, y: x * y, sets) # Cartesian product of sets
for i in indices:
call_some_other_function(*i)
This fails when I pass it a single set of integers, like
import pyomo.environ
myset = pyomo.environ.Set(initialize=[1, 2])
myfunc(*myset)
because then I'm evaluating *i
on an integer. What's an elegant way of handling this situation?
Upvotes: 0
Views: 268
Reputation: 3956
I think you're making things harder by implementing your own Cartesian product. Python's provided itertools.product
since 2.6, and it works with any number of input sets.
import itertools
def args(*args):
return repr(args)
def for_each_index(*sets):
if not sets:
print('No sets given. Doing something else.')
return
for index in itertools.product(*sets):
print('Do something with ' + args(*index) + '...')
return
I added the args
function solely to show the exact result of expanding *args
. You don't need it, except maybe for debugging.
Note also that there is no need to call len
to test if a tuple is non-empty. if not sets:
will do.
Upvotes: 0
Reputation: 152725
You can always check if it is an collections.Iterable
to catch cases where it is not iterable (lists, sets, etc. are iterables - integer aren't):
from collections import Iterable
a = 1
isinstance(a, Iterable) # returns False
a = [1,2,3]
isinstance(a, Iterable) # returns True
so just do a check before you pass it into the function:
if isinstance(myset, Iterable):
myfunc(*myset)
else:
# something else
Upvotes: 1