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コード はこれです。

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 exprそれぞれをに置き換えますresult.append(expr)
  3. return result関数の下部に行を挿入します。
  4. イェーイ-これ以上のyieldステートメントはありません!コードを読んで理解します。
  5. 関数を元の定義に戻します。

これを使用してyieldなしでコードを取得すると、これが得られます。コードが機能していません(関数は反復できません)。このコードをyieldなしで機能させるには、何を書く必要がありますか?

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

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

しかし、なぜあなたは利回りに反対しているのですか?ジェネレーターは、読みやすく効率的なコードを作成します。「YieldKeywordExplained」の記事のポイントは、それを省くことではなく、それを説明することでした。

投稿したジェネレーターコード:

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 に答える
2

問題は、元のコードがreturn通常とは異なる方法で使用されていることです。

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

ほとんどの場合return、ジェネレーターは必要ないため、ジェネレーターには表示されません。通常、ジェネレータは最後に単に「落ちる」。インタープリターはステートメントに遭遇することなくジェネレーターの最後に到達し、returnそれからスローすることを知っていStopIterationます。

この場合returnコードの作成者は、プロセスを「急ぐ」ためのステートメントを挿入しました。の場合K <= 0、実行する作業がなくなるため、ジェネレーターはスローできますが、ステートメントStopIterationがないと、ループに入り、誤った結果が生成されます。私の意見では、これを行うためのより明確な方法は次のようになります。returnfor

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 に答える