2010-07-27 5 views
16

루프에서 반복되는 시퀀스를 수정하는 것은 안전하지 않습니다 (목록과 같이 변경 가능한 시퀀스 유형에서만 발생할 수 있습니다). 반복되는 목록을 수정해야하는 경우 (예 : 선택한 항목을 복제 할 때) 사본을 반복해야합니다. 슬라이스 표기법이 특히 편리하게 :반복되는 시퀀스를 수정하는 것이 안전하지 않은 이유는 무엇입니까?

>>> for x in a[:]: # make a slice copy of the entire list 
    ... if len(x) > 6: a.insert(0, x) 
    ... 
    >>> a 
    ['defenestrate', 'cat', 'window', 'defenestrate'] 

단지 for x in a을 할 이유가 안전하지 않다?

+2

시도했을 때 어떤 결과를 얻었습니까? – SilentGhost

+0

나는 아래 질문에 대한 대답을 믿습니다. 전체 목록을 복사하지 않으려면 반복 작업 후에 실행할 수있는 작업 목록도 유지해야합니다. –

답변

13

:

파이썬에서 변경 가능한 순서를 반복하고 있으며이를 통해 반복되는 동안 순서가 변경되면, 그것은 항상 완전히 분명 무슨 일이 일어날되지 않습니다. 시퀀스를 반복하면서 시퀀스에 요소를 삽입하면 현재 시퀀스의 "다음"요소로 간주 될 수있는 요소는 무엇입니까? 다음 객체를 삭제하면 어떨까요?

이러한 이유로 변경하는 동안 변경 가능한 시퀀스를 반복하면 지정되지 않은 동작이 발생합니다. 목록이 어떻게 구현되는지에 따라 어떤 일이 발생할 수 있습니다. :-)

1

반복기를 반복하는 컬렉션을 수정하면 예기치 않게 동작 할 수 있습니다 (예 : 항목이 누락되거나 동일한 항목을 두 번 반환).

이 코드는 내가 그것을 실행하면 무한 루프 :

>>> a = [ 'foo', 'bar', 'baz' ] 
>>> for x in a: 
... if x == 'bar': a.insert(0, 'oops') 

반복자는 목록에있는 곳을 추적하는 인덱스를 사용하기 때문입니다. 목록의 시작 부분에 항목을 추가하면 다음 항목으로 진행되는 반복자 대신 '바'항목이 다시 반환됩니다.

12

이것은 많은 언어에서 일반적인 문제입니다. 선형 데이터 구조를 가지고 있고 그것을 반복하고 있다면, 구조가 어디에 있는지 추적해야합니다. 현재 색인이나 포인터 일 수도 있지만 "현재 위치"를 가리키는 손가락 일종입니다.

반복이 진행되는 동안 목록을 수정하면 커서가 잘못 표시 될 수 있습니다.

일반적인 문제는 커서 아래의 항목을 제거하고 모든 항목이 아래로 내려 가고 루프의 다음 반복이 커서를 증가 시키므로 의도하지 않게 항목을 건너 뛴다는 것입니다.

일부 데이터 구조 구현은 반복하는 동안 항목을 삭제할 수 있지만 대부분은 수행하지 않습니다. 너무 기술지고없이

+0

'for x in a :'에서 각 반복마다'a'가 평가됩니까? – haccks

+0

아니요, 반복기를 얻으려면 한 번 평가되고 반복기는 루프에 사용됩니다. –

+0

확인. 당신은 다음과 같이 말했습니다 : * 일반적인 문제는 커서 아래의 항목을 제거하고, 모든 것이 아래로 내려 가고, 루프의 다음 반복은 커서를 증가시키고 의도하지 않게 항목을 건너 뛴다는 것입니다. 'a'가 한 번만 평가되면'a'에 대한 모든 수정이 있습니까? – haccks

관련 문제