2014-03-25 38 views
1

如何创建一个类似于itertools.product()生成的Python生成器,但是它会遍历重复值列表?它会表现这样的嵌套循环for列表中的Python笛卡尔功率发生器

theSet = 'ABC' 
thePowers = range(4) 

for i in thePowers: 
    for j in itertools.product(theSet, repeat=i): 
     print j 

,但我想这是一个发电机,这样,这将产生相同的输出:

for p in myGenerator: 
    print p 

回答

1

你可以为它定义一个发电机功能..

>>> from itertools import product 
>>> def my_gen(letters, powers): 
...  for power in powers: 
...   for cartesian in product(letters, repeat=power): 
...    yield cartesian 
...   
...  
... 
>>> 

而且使用这样的:

>>> for p in my_gen("ABC", range(4)): 
... print p 
() 
('A',) 
('B',) 
('C',) 
('A', 'A') 
('A', 'B') 
('A', 'C') 
('B', 'A') 
('B', 'B') 
('B', 'C') 
('C', 'A') 
('C', 'B') 
('C', 'C') 
('A', 'A', 'A') 
('A', 'A', 'B') 
('A', 'A', 'C') 
('A', 'B', 'A') 
('A', 'B', 'B') 
('A', 'B', 'C') 
('A', 'C', 'A') 
('A', 'C', 'B') 
('A', 'C', 'C') 
('B', 'A', 'A') 
('B', 'A', 'B') 
('B', 'A', 'C') 
('B', 'B', 'A') 
('B', 'B', 'B') 
('B', 'B', 'C') 
('B', 'C', 'A') 
('B', 'C', 'B') 
('B', 'C', 'C') 
('C', 'A', 'A') 
('C', 'A', 'B') 
('C', 'A', 'C') 
('C', 'B', 'A') 
('C', 'B', 'B') 
('C', 'B', 'C') 
('C', 'C', 'A') 
('C', 'C', 'B') 
('C', 'C', 'C') 

您还可以使用生成器表达式!

>>> products = list(product("ABC", repeat=i) for i in range(4)) 
>>> result = list(x for lst in products for x in lst) 
>>> result 
[(), ('A',), ('B',), ('C',), ('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B 
', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C'), ('A', 'A', 'A'), ('A', 
'A', 'B'), ('A', 'A', 'C'), ('A', 'B', 'A'), ('A', 'B', 'B'), ('A', 'B', 'C'), (
'A', 'C', 'A'), ('A', 'C', 'B'), ('A', 'C', 'C'), ('B', 'A', 'A'), ('B', 'A', 'B 
'), ('B', 'A', 'C'), ('B', 'B', 'A'), ('B', 'B', 'B'), ('B', 'B', 'C'), ('B', 'C 
', 'A'), ('B', 'C', 'B'), ('B', 'C', 'C'), ('C', 'A', 'A'), ('C', 'A', 'B'), ('C 
', 'A', 'C'), ('C', 'B', 'A'), ('C', 'B', 'B'), ('C', 'B', 'C'), ('C', 'C', 'A') 
, ('C', 'C', 'B'), ('C', 'C', 'C')] 
1
from itertools import product 

def my_generator(values, *start_stop_step): 
    for i in range(*start_stop_step): 
     for j in product(values, repeat=i): 
      yield ''.join(j) 

for p in my_generator("ABC", 4): 
    print(p) 

这给

# <= that was a null string ie '' 
A 
B 
C 
AA 
AB 
AC 
BA 
BB 
... 
CCA 
CCB 
CCC 
+0

足够的信息在这里做我想做的,谢谢!我标记了msvalkon的答案,因为它给出了我的稍微更一般的问题的具体答案。 –

1

您可以使用'yield'关键字很容易地做到这一点。下面是我发现很清楚一个博客:https://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

import itertools 

def iterate(): 
    theSet = 'ABC' 
    thePowers = range(4) 

    output = [] 
    for i in thePowers: 
     for j in itertools.product(theSet, repeat=i): 
      output.append(j) 
    return output 

def generate(): 
    theSet = 'ABC' 
    thePowers = range(4) 

    for i in thePowers: 
     for j in itertools.product(theSet, repeat=i): 
      yield j 

a = iterate() 
b = [output for output in generate()] 
print(a == b) # True 

最后一条语句向我们保证,输出是相同的。我想你会想做更复杂的事情,而不是从生成的值中创建列表。