1

以下のコードがありますが、何らかの理由で while ループが終了しません。

def iterator(i, f):
    print len(f)
    print i
    while i < len(f):
        if i == 0:
            print "Restarted."
        else:
            print "iterate."
        function()
    return f

printステートメントは実際には必要ありませんが、カウンターiは別の関数によって増加するため、問題がないことを確認したかった. f4 つのアイテムを含むリストの場合、次のように出力されます。

4, 0, Restarted.
4, 1, iterate.
4, 2, iterate.
4, 3, iterate.
4, 4, iterate.
4, 4, iterate.
etc..

なぜ while ループに入り続けるのか理解できませi = 4len(f) = 4。ループを破って return 関数を実行するはずですが、何らかの理由で実行されません。

条件が false になったときに while ループが終了しない理由を説明できる人はいますか?

編集:何が起こっているのかをよりよく説明するためのコード。また、iによって変更されることも明確にしました。それが理にかなっていることを願っています。function()iteratori

f = [0,1,2,3]
i = 0

def iterator(i, f):
    print i
    while i < len(f):
        print i
        if i == 0:
            print "Restarted."
        else:
            print "iterate."
        function(i, f)
    return f


def function(i, f):
    i += 1
    iterator(i, f)

iterator(i,f)

この結果は次のようになります。

0, 0, Restarted.
1, 1, iterate.
2, 2, iterate.
3, 3, iterate.
4, 3, iterate.
4, 3, iterate.
etc.
4

3 に答える 3

6

カウンター i は別の関数によって増加します

不可能。これはローカル整数です。出力される値は、別の変数の値です。print iループ内に追加してみてください。

int不変の型です。これは、このタイプのオブジェクトがその値を変更できないことを意味します。変更できるのは、変数が保持しているオブジェクトだけです。

def inc(i):
    i+=1

i=0
inc(i)
print i

出力:

0

どうしてこれなの?i内側inci外側は2つの独立変数だからです。i+=1内部incは、「ローカル変数iが新しいオブジェクトを指すようにする」という意味だけ2です。グローバルにはまったく影響しませんi。C や Java (および他のほとんどの主要言語のデフォルト) と同様に、変数は値によって渡されます

このループを終了できる唯一の方法は、 がリストであり、したがって変更可能であると仮定して、functionから要素を削除する場合です。ff


これは、新しいバージョンと同等のコードです。ループだけでなく、再帰を使用していることに注意してください。すぐにスタックから外れます。

f = [0,1,2,3]
i = 0

def iterator(i, f):
    print i
    while i < len(f):
        '''if the recursion is less than 4 levels deep: loop forever
           else: don't loop at all'''
        print i
        if i == 0:
            print "Restarted."
        else:
            print "iterate."
        iterator(i+1, f)
    return f

出力:

0, 0, Restarted. # 0 level recursion, 1st iteration
1, 1, iterate.   # 1 level recursion, 1st iteration
2, 2, iterate.   # 2 level recursion, 1st iteration
3, 3, iterate.   # 3 level recursion, 1st iteration
4, 3, iterate.   # 3 level recursion, 2nd iteration, the condition now is false
4, 3, iterate.   # 3 level recursion, 3rd iteration  
4, 3, iterate.   # 3 level recursion, 4th iteration
4, 3, iterate.   # 3 level recursion, 5th iteration 

等々。

于 2013-07-01T13:40:09.953 に答える
2

あなたの問題は、グローバル変数とローカル変数を正しく理解していないことです。この名前iは、ループの内側とループの外側では異なる意味を持ちます。これを試して、私が何を意味するかを確認してください。

def iterator(i, f):
    # Your code

def function(i, f):
    # Your code

iterator(0, [0, 1, 2, 3])

iもちろん、グローバルに定義されていなくても、これは引き続き実行されます。これは、 という名前iの関数引数がiあり、関数内で新しい意味を持つためです。数値は不変であるため、関数内で「変更」するたびに、「わかりました。この関数内で別の数値を指すようになりiます」と言っているだけです。i基になる番号を変更していません。

問題を解決するには 2 つの方法があります。手っ取り早い方法は、両方の関数からパラメーターを削除することです。これiにより、グローバル変数のみを参照するようになりますi

i = 0
f = range(4)
def iterator():
    # etc
def function():
    # etc
iterator()

ただし、このようなグローバル変数の使用はお勧めできません。クリーンではないため、デバッグが難しく、他の関数がそれを把握して予期しない動作を引き起こす可能性があるためです...一般的には良いアイデアではありません. 代わりに、関数のシグネチャを保持できますが、戻り値を使用して、やりたいことを何でも実行できます。このようなもの:

global_f = [0,1,2,3]
global_i = 0

def iterator(i, f):
    while i < len(f):
        if i == 0:
            print "Restarted."
        else:
            print "iterate."
        i = function(i, f) # Reassign i or it won't be changed!!
    return f

def function(i, f):
    return i + 1

iterator(global_i, global_f)

何をすべきかわからないので、単純な return ステートメントに単純化したことに注意functionしてください。一般に、2 つの関数が互いに呼び出す場合は注意してください。再帰を行うと、非常に簡単に無限ループに陥ります。

于 2013-07-01T14:06:27.617 に答える