如何在Python中迭代集合的笛卡尔积时处理边缘情况?

时间:2016-03-14 23:10:58

标签: python set

我的函数为零或更多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)

当我传递一组整数时,这会失败,例如

import pyomo.environ
myset = pyomo.environ.Set(initialize=[1, 2])
myfunc(*myset)

因为我在整数上评估*i。什么是处理这种情况的优雅方式?

2 个答案:

答案 0 :(得分:1)

你总是可以检查它是否是collections.Iterable来捕捉它不可迭代的情况(列表,集合等是迭代的 - 整数不是):

from collections import Iterable
a = 1
isinstance(a, Iterable) # returns False
a = [1,2,3]
isinstance(a, Iterable) # returns True

所以在将其传递给函数之前,请先进行检查:

if isinstance(myset, Iterable):
    myfunc(*myset)
else:
    # something else

答案 1 :(得分:0)

我认为你通过实施自己的笛卡尔产品会让事情变得更难。自2.6以来,Python提供了itertools.product,它适用于任意数量的输入集。

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

我添加了args功能,仅用于显示展开*args的确切结果。除了调试之外,你不需要它。

另请注意,无需调用len来测试元组是否为非空。 if not sets:会这样做。