2012-07-23 92 views
3

总之。我怎么写别的东西比这个:for another in combinationOfK(K-1, L[i+1:]):我的函数combinationOfK(...)是不可迭代的。用迭代的东西代替函数

我想了解从here解决方案的代码。 Problem 26: Generate the combinations of K distinct objects chosen from the N elements of a list
我知道什么产量。但我正在尝试编写代码而没有 a yield声明。代码与产量陈述是这样的。

def combination(K, L): 
    if K<=0: 
     yield [] 
     return 
    for i in range(len(L)): 
     thisone = L[i:i+1] 
     for another in combination(K-1, L[i+1:]): 
      yield thisone + another 

The question, yield-keyword-explained给了我一个想法,我可以代替产量。他们给recepie,这不是为我工作,就是:

当你看到yield语句的功能,应用此容易 招明白会发生什么:

  1. 插入线result = []在函数的开始处。
  2. result.append(expr)替换每个yield expr
  3. 在函数的底部插入一行return result
  4. Yay - 没有更多yield声明!阅读并找出代码。
  5. 将功能还原为原始定义。

以此来获得不屈服的代码给我这个。代码不工作(该函数不可迭代)。 我必须写些什么才能让代码在没有收益的情况下工作?

def combinationOfK(K,L): 
    result = [] 
    if K <= 0: 
     result.append([]) 
     return 
    for i in range(len(L)): 
     thisone = L[i:i+1] 
     for another in combinationOfK(K-1, L[i+1:]): # the error 
      result.append(thisone + another) 
    return result 

我使用这个代码来测试功能,

the_list = ['a','b','c','d','e'] 
print list(combinationOfK(2, the_list)) 

提高错误TypeError: 'NoneType' object is not iterable

+3

你忘了缩进你的最后一个函数5日线。 – 2012-07-23 15:57:46

+0

固定。现在它缩进了。 – 2012-07-23 16:35:48

回答

2

问题是您的原始代码使用return以不寻常的方式。

def combination(K, L): 
    if K<=0: 
     yield [] 
     return # <--- hmmm 

大多数时候,你不会看到return在发电机,因为你不经常需要它。通常,发电机最终会“脱落”;解释者到达发电机的末端而没有遇到return声明,然后它知道抛出StopIteration

这个的情况下,代码的作者插入了return语句来“快速”处理。当K <= 0时,不需要做更多的工作,所以发生器可以抛出StopIteration - 但是没有return声明,它将进入for循环,产生不正确的结果。在我看来,更明确的方式来做到这一点本来像这样:

def combination(K, L): 
    if K<=0: 
     yield [] 
    else: 
     for i in range(len(L)): 
      thisone = L[i:i+1] 
      for another in combination(K-1, L[i+1:]): 
       yield thisone + another 

现在的改建工程按预期:

def combination2(K, L): 
    result = [] 
    if K <= 0: 
     result.append([]) 
    else: 
     for i in range(len(L)): 
      thisone = L[i:i + 1] 
      for another in combination2(K - 1, L[i + 1:]): 
       result.append(thisone + another) 
    return result 
2

正如Vincent提到的,由于第5行,您的函数返回None。将其更改为:

def combinationOfK(K,L): 
    result = [] 
    if K <= 0: 
     result.append([]) 
     return result 
    for i in range(len(L)): 
     thisone = L[i:i+1] 
     for another in combinationOfK(K-1, L[i+1:]): # the error 
      result.append(thisone + another) 
    return result 

但是,您为什么反对收益率?生成器使可读,高效的代码。 Yield关键字解释文章的重点不是放弃它,而是解释它。

在生成的代码,您发布的评论:

def combination(K, L): 
    if K<=0: 
     yield [] 
     return 
    for i in range(len(L)): 
     thisone = L[i:i+1] 
     for another in combination(K-1, L[i+1:]): 
      yield thisone + another 

return声明并不意味着同样的事情return确实在正常功能。在生成器中,return立即引发StopIteration,这会导致调用方停止迭代生成器对象。

+0

@senderle更正。 – 2012-07-23 17:01:30