在 Python 中迭代集合的笛卡尔积时如何处理边缘情况?
How to handle edge case when iterating over cartesian product of sets in Python?
我有零个或多个函数 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
。处理这种情况的优雅方式是什么?
您始终可以检查它是否是 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
我认为您通过实施自己的笛卡尔积让事情变得更难。 Python 从 2.6 开始提供 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:
就行了。
我有零个或多个函数 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
。处理这种情况的优雅方式是什么?
您始终可以检查它是否是 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
我认为您通过实施自己的笛卡尔积让事情变得更难。 Python 从 2.6 开始提供 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:
就行了。