2015-09-13 9 views
4

对不起,如果标题措辞不当,我不知道如何对其进行定义。我有一个函数,基本上迭代2维可迭代的第二维。下面是一个简单再生产:发电机未按预期关闭数据

words = ['ACGT', 'TCGA'] 

def make_lists(): 
    for i in range(len(words[0])): 
     iter_ = iter([word[i] for word in words]) 
     yield iter_ 

lists = list(make_lists()) 

for list_ in lists: 
    print(list(list_)) 

运行此输出:

['A', 'T'] 
['C', 'C'] 
['G', 'G'] 
['T', 'A'] 

我想获得,而不必评估words发电机,以防words是很长,所以我尝试以下:

words = ['ACGT', 'TCGA'] 

def make_generators(): 
    for i in range(len(words[0])): 
     gen = (word[i] for word in words) 
     yield gen 

generators = list(make_iterator()) 

for gen in generators: 
    print(list(gen)) 

但是,运行输出:

['T', 'A'] 
['T', 'A'] 
['T', 'A'] 
['T', 'A'] 

我不确定到底发生了什么。我猜想这与发电商的理解有关,因为它们都是分享的,而不是在收购时关闭它的范围。如果我在一个单独的函数中创建生成器并从该函数返回它似乎工作。

回答

3

i现在是那些生成器的自由变量,他们现在将使用它的最后一个值,即3.简单地说,他们知道它们应该从哪里获取值i,但不知道创建时的实际值为i。所以,这样的事情:

def make_iterator(): 
    for i in range(len(words[0])): 
     gen = (word[i] for word in words) 
     yield gen 
    i = 0 # Modified the value of i 

将导致:

['A', 'T'] 
['A', 'T'] 
['A', 'T'] 
['A', 'T'] 

生成器表达式作为函数范围内实施,而另一方面列表解析运行的时候了,并在可获取的i值(列表理解在Python 3中作为函数范围实现,但不同之处在于它们不是懒惰的)

修复将使用一个内部函数来捕获的实际值在每个循环使用默认参数值:

words = ['ACGT', 'TCGA'] 

def make_iterator(): 
    for i in range(len(words[0])): 
     # default argument value is calculated at the time of 
     # function creation, hence for each generator it is going 
     # to be the value at the time of that particular iteration 
     def inner(i=i): 
      return (word[i] for word in words) 
     yield inner() 

generators = list(make_iterator()) 

for gen in generators: 
    print(list(gen)) 

您可能还需要阅读: