HTF*_*HTF -1 python cartesian-product python-itertools
假设我有两个可迭代对象,一个是有限的,一个是无限的:
import itertools
teams = ['A', 'B', 'C']
steps = itertools.count(0, 100)
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以避免嵌套的 for 循环并使用itertools模块中的无限迭代器之一,例如cycle或repeat来获取这些迭代器的笛卡尔积。
循环应该是无限的,因为 的停止值steps预先未知。
预期输出:
$ python3 test.py
A 0
B 0
C 0
A 100
B 100
C 100
A 200
B 200
C 200
etc...
Run Code Online (Sandbox Code Playgroud)
带有嵌套循环的工作代码:
from itertools import count, cycle, repeat
STEP = 100
LIMIT = 500
TEAMS = ['A', 'B', 'C']
def test01():
for step in count(0, STEP):
for team in TEAMS:
print(team, step)
if step >= LIMIT: # Limit for testing
break
test01()
Run Code Online (Sandbox Code Playgroud)
from itertools import product
for i, j in product(range(0, 501, 100), 'ABC'):
print(j, i)
Run Code Online (Sandbox Code Playgroud)
正如文档所说product(A, B),相当于((x,y) for x in A for y in B). 如您所见,product产生一个元组,这意味着它是一个生成器并且不会在内存中创建列表以正常工作。
这个函数大致相当于下面的代码,只不过实际的实现不会在内存中建立中间结果:
Run Code Online (Sandbox Code Playgroud)def product(*args, **kwds): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = map(tuple, args) * kwds.get('repeat', 1) result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod)
但是itertools.product由于已知问题,您不能使用无限循环:
根据文档, itertools.product 相当于生成器表达式中的嵌套 for 循环。但是, itertools.product(itertools.count(2010)) 不是。
Run Code Online (Sandbox Code Playgroud)>>> import itertools >>> (year for year in itertools.count(2010)) <generator object <genexpr> at 0x026367D8> >>> itertools.product(itertools.count(2010)) Traceback (most recent call last): File "<stdin>", line 1, in <module> MemoryErroritertools.product 的输入必须是有限迭代的有限序列。
对于无限循环,您可以使用此代码。