개발/Python

[파이썬] 반복 변수를 수정해도 후속 반복에 영향을 주지 않는 이유

MinorMan 2023. 8. 12. 14:48
반응형

<질문>

문제가 있는 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

나는for루프는 C에서 변수에 대한 새로운 범위를 생성하지만 Python에 대해서는 전혀 모릅니다. 의 값이 왜i에서 변경하지forPython에서 반복하고 예상되는 출력을 얻기 위한 해결책은 무엇입니까?

for 루프 중에 목록 항목을 수정하는 방법을 참조하십시오. 원본 시퀀스를 수정하는 방법. 물론 3.x에서 range 불변 객체를 생성하므로 여전히 작동하지 않습니다.


<답변1>

for 루프는 다음의 모든 숫자를 반복합니다.range(10), 그건,[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

<답변2>

당신은 당신의for-loop파이썬에서 다음 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;
}

그래서 수정iin the 루프는 예상한 효과가 없습니다.

당신은 볼 수 있습니다disassembly of the 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        
>>> 

이 부분creates a range between 0 and 10그리고 그것을 깨닫는다:

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

이 시점에서 스택의 맨 위에 범위가 포함됩니다.

이것gets an iterator over the object on the top of the stack, 즉 범위:

         15 GET_ITER  

이 시점에서 스택의 맨 위에는 구현된 범위에 대한 반복자가 포함됩니다.

FOR_ITER begins iterating over the loop스택 맨 위에 있는 반복자를 사용하여:

    >>   16 FOR_ITER                36 (to 55)

이 시점에서 스택의 맨 위에는 반복자의 다음 값이 포함됩니다.

그리고 여기서 당신은 그것을 볼 수 있습니다the top of the stack is popped and assigned to i:

         19 STORE_FAST               0 (i)

그래서i루프에서 수행하는 작업에 관계없이 덮어씁니다.

여기overview of stack machines전에 이것을 본 적이 없다면.


<답변3>

Python의 for 루프는 실제로 for-each 루프입니다. 각 루프가 시작될 때,iiterator의 다음 요소로 설정됩니다(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

<답변4>

어떤 이유로 정말로 변경하고 싶다면 에 3을 추가하십시오.i같을 때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

<답변5>

파이썬 2.7에서는 범위 함수가 목록을 생성하는 반면 파이썬 3.x 버전에서는 파이썬 2.7의 xrange와 유사하게 목록이 아닌 순회만 가능한 '범위' 클래스 객체를 생성합니다.

범위(1, 10)를 반복할 때가 아니라 결국 목록 유형 개체에서 읽고 for 루프에 도달할 때마다 i가 새 값을 사용합니다.

이것은 다음과 같습니다.

for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    if i==5:
        i+=3
    print(i)

값을 변경해도 목록의 반복 순서는 변경되지 않습니다.


<답변6>

반복할 때마다 재설정되므로 루프 내에서 무엇을 하든 상관 없습니다. 아무것도 하지 않는 유일한 시간은 i가 5일 때이며 여기에 3을 더합니다. 루프백하면 i를 목록의 다음 번호로 다시 설정합니다. 당신은 아마while여기.


<답변7>

파이썬의forloop는 단순히 제공된 값 시퀀스를 반복합니다. "foreach"라고 생각하세요. 이러한 이유로 변수를 수정해도 루프 실행에는 영향을 미치지 않습니다.

이것은 에 잘 설명되어 있습니다.the tutorial.


<답변8>

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

<답변9>

다음과 같이 수정할 수 있습니다.for고리:

for i in range (0,10):
    if i in [5, 6, 7]:
        continue
    print(i)

<답변10>

내 생각에 유사한 코드는 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
반응형