我想这是一个学术问题,但第二个结果对我来说没有意义.它不应该像第一个一样彻底空洞吗?这种行为的理由是什么?
from itertools import product one_empty = [ [1,2], [] ] all_empty = [] print [ t for t in product(*one_empty) ] # [] print [ t for t in product(*all_empty) ] # [()]
更新
感谢所有的答案 - 非常有用.
维基百科对Nullary Cartesian产品的讨论提供了一个明确的陈述:
没有集合的笛卡尔积......是包含空元组的单例集.
这里有一些代码可以用来处理来自sth的深刻答案:
from itertools import product def tproduct(*xss): return ( sum(rs, ()) for rs in product(*xss) ) def tup(x): return (x,) xs = [ [1, 2], [3, 4, 5] ] ys = [ ['a', 'b'], ['c', 'd', 'e'] ] txs = [ map(tup, x) for x in xs ] # [[(1,), (2,)], [(3,), (4,), (5,)]] tys = [ map(tup, y) for y in ys ] # [[('a',), ('b',)], [('c',), ('d',), ('e',)]] a = [ p for p in tproduct( *(txs + tys) ) ] b = [ p for p in tproduct( tproduct(*txs), tproduct(*tys) ) ] assert a == b
sth.. 10
从数学的角度来看,无任何元素的产品应该产生操作产品的中性元素,无论是什么.
例如,对于整数,乘法的中性元素是1,因为对于所有整数a,1·a = a.所以整数的空积应该是1.当实现一个返回数字列表产品的python函数时,这自然会发生:
def iproduct(lst): result = 1 for i in lst: result *= i return result
要使用此算法计算正确的结果,result
需要初始化1
.这导致1
在空列表上调用函数时的返回值.
对于函数而言,此返回值也非常合理.如果您首先连接两个列表然后构建元素的产品,或者如果您首先构建两个单独列表的产品然后乘以结果,那么使用良好的产品功能并不重要:
iproduct(xs + ys) == iproduct(xs) * iproduct(ys)
如果xs
或者ys
为空则仅在以下情况下有效iproduct([]) == 1
.
现在product()
迭代器上的复杂程度越来越高.从数学的角度来看,这也product([])
应该返回该操作的中性元素,无论是什么.这是不是[]
因为product([], xs) == []
,而对于中性元素product([], xs) == xs
应该持有.事实证明,这[()]
也不是一个中性元素:
>>> list(product([()], [1,2,3])) [((), 1), ((), 2), ((), 3)]
事实上,product()
根本不是一个非常好的数学产品,因为上面的等式不成立:
product(*(xs + ys)) != product(product(*xs), product(*ys))
每个产品应用程序都会生成一个额外的元组层,并且没有办法解决这个问题,因此甚至不可能存在真正的中性元素.[()]
虽然它非常接近,它不会添加或删除任何元素,它只是为每个元素添加一个空元组.
[()]
事实上,这个稍微适应的产品函数的中性元素只能在元组列表上运行,但不会在每个应用程序上添加额外的元组层:
def tproduct(*xss): # the parameters have to be lists of tuples return (sum(rs, ()) for rs in product(*xss))
对于此功能,上述产品等式成立:
def tup(x): return (x,) txs = [map(tup, x) for x in xs] tys = [map(tup, y) for y in ys] tproduct(*(txs + tys)) == tproduct(tproduct(*txs), tproduct(*tys))
通过将输入列表打包到元组中的附加预处理步骤,tproduct()
给出了相同的结果product()
,但从数学的角度来看表现更好.它的中性元素是[()]
,
因此[()]
,作为这种列表乘法的中性元素是有道理的.即使它不完全适合product()
它也是这个函数的一个很好的选择,因为它允许定义tproduct()
而不需要为空输入引入特殊情况.
从数学的角度来看,无任何元素的产品应该产生操作产品的中性元素,无论是什么.
例如,对于整数,乘法的中性元素是1,因为对于所有整数a,1·a = a.所以整数的空积应该是1.当实现一个返回数字列表产品的python函数时,这自然会发生:
def iproduct(lst): result = 1 for i in lst: result *= i return result
要使用此算法计算正确的结果,result
需要初始化1
.这导致1
在空列表上调用函数时的返回值.
对于函数而言,此返回值也非常合理.如果您首先连接两个列表然后构建元素的产品,或者如果您首先构建两个单独列表的产品然后乘以结果,那么使用良好的产品功能并不重要:
iproduct(xs + ys) == iproduct(xs) * iproduct(ys)
如果xs
或者ys
为空则仅在以下情况下有效iproduct([]) == 1
.
现在product()
迭代器上的复杂程度越来越高.从数学的角度来看,这也product([])
应该返回该操作的中性元素,无论是什么.这是不是[]
因为product([], xs) == []
,而对于中性元素product([], xs) == xs
应该持有.事实证明,这[()]
也不是一个中性元素:
>>> list(product([()], [1,2,3])) [((), 1), ((), 2), ((), 3)]
事实上,product()
根本不是一个非常好的数学产品,因为上面的等式不成立:
product(*(xs + ys)) != product(product(*xs), product(*ys))
每个产品应用程序都会生成一个额外的元组层,并且没有办法解决这个问题,因此甚至不可能存在真正的中性元素.[()]
虽然它非常接近,它不会添加或删除任何元素,它只是为每个元素添加一个空元组.
[()]
事实上,这个稍微适应的产品函数的中性元素只能在元组列表上运行,但不会在每个应用程序上添加额外的元组层:
def tproduct(*xss): # the parameters have to be lists of tuples return (sum(rs, ()) for rs in product(*xss))
对于此功能,上述产品等式成立:
def tup(x): return (x,) txs = [map(tup, x) for x in xs] tys = [map(tup, y) for y in ys] tproduct(*(txs + tys)) == tproduct(tproduct(*txs), tproduct(*tys))
通过将输入列表打包到元组中的附加预处理步骤,tproduct()
给出了相同的结果product()
,但从数学的角度来看表现更好.它的中性元素是[()]
,
因此[()]
,作为这种列表乘法的中性元素是有道理的.即使它不完全适合product()
它也是这个函数的一个很好的选择,因为它允许定义tproduct()
而不需要为空输入引入特殊情况.