Heres pythonコードimに問題がある:
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
for
ループがCの変数の新しいスコープを作成することは知っていますが、Pythonについてはわかりません。 python)のi
ループでfor
の値が変化しない理由と、予想される出力を得るための対策を説明できる人はいますか。
Forループは、range(10)
のすべての数値、つまり[0,1,2,3,4,5,6,7,8,9]
。i
のcurrent値を変更しても、範囲内の次の値には影響しません。
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
あなたはあなたのfor-loop
in 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 code の逆アセンブリを見ると、これを確認できます。
>>> 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
>>>
この部分 〜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はループの反復を開始します estackの先頭にある反復子を使用します。
>> 16 FOR_ITER 36 (to 55)
この時点で、スタックの最上部にはイテレーターの次の値が含まれています。
そして、ここで スタックのトップがポップされ、i
に割り当てられていることがわかります。
19 STORE_FAST 0 (i)
したがって、i
は、ループで何をするかに関係なく上書きされます。
スタックマシンの概要 は、これを見たことがない場合です。
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
何らかの理由で本当に5
に等しいときにi
に3を追加し、次の要素をスキップしたい場合(これは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
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
繰り返しごとにリセットされるので、ループ内で何をするかは重要ではありません。何かをするのは、iが5のときだけで、その後3を追加します。ループバックすると、リスト内の次の番号にiが設定されます。おそらくここでwhile
を使用したいでしょう。
Pythonのfor
ループは、指定された値のシーケンスを単純にループします。これを「foreach」と考えてください。このため、変数を変更してもループの実行には影響しません。
これは チュートリアル で詳しく説明されています。
python 2.7範囲関数はリストを作成しますが、python 3.xバージョンでは、リストではなく反復可能な 'range'クラスオブジェクトを作成します。 xrange in python 2.7。
Range(1、10)を繰り返し処理しているときではなく、最終的にはリスト型オブジェクトから読み取りを行い、forループに達するたびに新しい値を取得します。
これは次のようなものです:
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
if i==5:
i+=3
print(i)
値を変更しても、リストの反復順序は変更されません。
for
ループに次の変更を加えることができます。
for i in range (0,10):
if i in [5, 6, 7]:
continue
print(i)
私の見解では、類似したコードはwhileループではなく、実行時にリストを編集するforループです。
originalLoopRange = 5
loopList = list(range(originalLoopRange))
timesThroughLoop = 0
for loopIndex in loopList:
print(timesThroughLoop, "count")
if loopIndex == 2:
loopList.pop(3)
print(loopList)
print(loopIndex)
timesThroughLoop += 1