3

简而言之。我该如何写除此之外的其他内容:for another in combinationOfK(K-1, L[i+1:]):我的函数 combinationOfK(...) 不可迭代。

我试图从这里理解代码,解决方案。Problem 26: Generate the combinations of K distinct objects chosen from the N elements of a list
我知道 yield 的作用。但我试图在没有声明的情况下编写代码yield带有 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

这个问题yield-keyword-explained让我想到我可以取代产量。他们给的收据对我不起作用,是:

当你看到一个带有yield语句的函数时,应用这个简单的技巧来理解会发生什么:

  1. result = []在函数的开头插入一行。
  2. 将每个替换yield exprresult.append(expr)
  3. return result在函数底部插入一行。
  4. 是的 - 没有更多的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

4

2 回答 2

2

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

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

大多数时候你不会return在生成器中看到它,因为你并不经常需要它。通常,生成器最后会简单地“脱落”。解释器在没有遇到语句的情况下到达生成器的末尾return,然后它知道 throw 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
于 2012-07-23T16:31:50.323 回答
2

正如文森特所提到的,由于第 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 Keyword Explained 文章的重点不是要省略它,而是要解释它。

在您发布的生成器代码中:

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,这会导致调用者停止迭代生成器对象。

于 2012-07-23T16:27:54.690 回答