50

私が問題を抱えているPythonコードは次のとおりです。

for i in range (0,10):
    if i==5:
        i+=3
    print i

出力は次のようになると予想していました。

0
1
2
3
4
8
9

ただし、通訳者は次のように吐き出します。

0
1
2
3
4
8
6
7
8
9

forC でループが変数の新しいスコープを作成することは知っていますが、Python についてはわかりません。iPythonのループで not の値が変化しないのはなぜforですか? また、期待される出力を得るにはどうすればよいですか?

4

10 に答える 10

52

range(10)forループは、内のすべての数値、つまり、を繰り返し処理します[0,1,2,3,4,5,6,7,8,9]の現在の
を変更しても、範囲内の次の値には影響しません。i

whileループを使用すると、目的の動作を得ることができます。

i = 0
while i < 10:
    # do stuff and manipulate `i` as much as you like       
    if i==5:
        i+=3

    print i

    # don't forget to increment `i` manually
    i += 1
于 2013-03-12T13:56:44.103 に答える
24

Cコードとの類推

あなたはあなたfor-loopのPythonがこのCコードのようなものだと想像しています:

for (int i = 0; i < 10; i++)
    if (i == 5)
        i += 3;

これは、次の C コードに似ています。

int r[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (int j = 0; j < sizeof(r)/sizeof(r[0]); j++) {
    int i = r[j];
    if (i == 5)
        i += 3;
}

そのため、ループ内で変更iしても、期待した効果は得られません。

分解例

Python コードの逆アセンブリを見ると、次のことがわかります。

>>> from dis import dis
>>> def foo():
...     for i in range (0,10):
...         if i==5:
...             i+=3
...         print i
... 
>>> dis(foo)
  2           0 SETUP_LOOP              53 (to 56)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (0)
              9 LOAD_CONST               2 (10)
             12 CALL_FUNCTION            2
             15 GET_ITER            
        >>   16 FOR_ITER                36 (to 55)
             19 STORE_FAST               0 (i)

  3          22 LOAD_FAST                0 (i)
             25 LOAD_CONST               3 (5)
             28 COMPARE_OP               2 (==)
             31 POP_JUMP_IF_FALSE       47

  4          34 LOAD_FAST                0 (i)
             37 LOAD_CONST               4 (3)
             40 INPLACE_ADD         
             41 STORE_FAST               0 (i)
             44 JUMP_FORWARD             0 (to 47)

  5     >>   47 LOAD_FAST                0 (i)
             50 PRINT_ITEM          
             51 PRINT_NEWLINE       
             52 JUMP_ABSOLUTE           16
        >>   55 POP_BLOCK           
        >>   56 LOAD_CONST               0 (None)
             59 RETURN_VALUE        
>>> 

この部分は、0 から 10 までの範囲を作成し、それを実現します。

          3 LOAD_GLOBAL              0 (range)
          6 LOAD_CONST               1 (0)
          9 LOAD_CONST               2 (10)
         12 CALL_FUNCTION            2

この時点で、スタックの一番上に範囲が含まれています。

これは、スタックの一番上にあるオブジェクト、つまり範囲の反復子を取得します。

         15 GET_ITER  

この時点で、スタックの一番上には、実現された範囲の反復子が含まれています。

FOR_ITER は、スタックの一番上にある反復子を使用して、ループの反復を開始します。

    >>   16 FOR_ITER                36 (to 55)

この時点で、スタックの一番上には反復子の次の値が含まれています。

ここでは、スタックの一番上がポップされ、 に割り当てられてiいることがわかります。

         19 STORE_FAST               0 (i)

そのiため、ループで何をしても上書きされます。

これまでに見たことがない場合は、スタック マシンの概要を次に示します。

于 2013-03-12T14:11:13.583 に答える
17

Pythonのforループは、実際にはfor-eachループです。各ループの開始時に、iはイテレータの次の要素に設定されます(range(0, 10)あなたの場合)。の値はi各ループの開始時に再設定されるため、ループ本体で値を変更しても、次の反復の値は変更されません。

つまり、作成したforループは、次のwhileループと同等です。

_numbers = range(0, 10) #the list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_iter = iter(_numbers)
while True:
    try:
        i = _iter.next()
    except StopIteration:
        break

    #--YOUR CODE HERE:--
    if i==5:
        i+=3
    print i
于 2013-03-12T13:57:19.757 に答える
5

何らかの理由で add 3 をiwhen it is equal to に変更し5、次の要素をスキップしたい場合 (これは、C 3 要素のポインタを進めるようなものです)、イテレータを使用して、そこから数ビットを消費できます。 :

from collections import deque
from itertools import islice

x = iter(range(10)) # create iterator over list, so we can skip unnecessary bits
for i in x:
    if i == 5:             
        deque(islice(x, 3), 0) # "swallow up" next 3 items
        i += 3 # modify current i to be 8
    print i

0
1
2
3
4
8
9
于 2013-03-12T14:05:08.980 に答える
1

反復ごとにリセットされるので、ループ内で何をするかは重要ではありません。それが何かをするのは、私が5のときだけで、それから3を追加します。ループバックすると、リスト内の次の番号に戻ります。おそらくここを使用したいと思うでしょうwhile

于 2013-03-12T13:56:33.357 に答える
1

Pythonのforループは、提供された値のシーケンスをループするだけです。これを「foreach」と考えてください。このため、変数を変更してもループの実行には影響しません。

これはチュートリアルで詳しく説明されています。

于 2013-03-12T13:56:40.593 に答える
1
it = iter(xrange (0,10))
for i in it:
    if i==4: all(it.next() for a in xrange(3))
    print i

また

it = iter(xrange (0,10))
itn = it.next
for i in it:
    if i==4: all(itn() for a in xrange(3))
    print i
于 2013-03-12T16:27:16.440 に答える