programing

Python: 외부 루프에서 다음 반복으로 계속 진행

showcode 2023. 6. 19. 21:48
반응형

Python: 외부 루프에서 다음 반복으로 계속 진행

파이썬의 외부 루프에서 다음 반복을 계속할 수 있는 내장된 방법이 있는지 알고 싶었습니다.예를 들어, 다음 코드를 생각해 보십시오.

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue
    ...block1...

저는 이 계속 진술서가 JJ 루프를 종료하고 ii 루프의 다음 항목으로 이동하기를 원합니다.(플래그 변수를 설정하여) 다른 방법으로 이 논리를 구현할 수 있지만, 이를 수행하는 쉬운 방법이 있습니까, 아니면 너무 많은 것을 요구하는 것과 같은 것입니까?

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            break
    else:
        ...block1...

Break내부 루프가 중단되고 블록 1이 실행되지 않습니다(내부 루프가 정상적으로 종료된 경우에만 실행됨).

for i in ...:
    for j in ...:
        for k in ...:
            if something:
                # continue loop i

일반적인 경우, 여러 수준의 루핑이 있을 때break루프 상위 중 진행하려는 ). 할 수 . 다음 중 하나를 수행할 수 있습니다.

탈출하려는 루프를 함수로 재팩터링

def inner():
    for j in ...:
        for k in ...:
            if something:
                return


for i in ...:
    inner()

단점은 이전에 범위에 포함되었던 몇 가지 변수를 새 함수에 전달해야 할 수도 있다는 것입니다.매개 변수로 전달하거나, 개체에 대한 인스턴스 변수로 만들거나(이 함수에 대해서만 새 개체를 생성하는 것이 적절하다면), 전역 변수, 싱글톤 등(으음, 으음)을 사용할 수 있습니다.

또는 정의할 수 있습니다.inner중첩 함수로서 필요한 것을 캡처하도록 합니다(더 느릴 수도 있음).

for i in ...:
    def inner():
        for j in ...:
            for k in ...:
                if something:
                    return
    inner()

예외 사용

철학적으로, 이것이 필요할 때 구조화된 프로그래밍 구성 요소를 통해 프로그램 흐름을 깨는 예외입니다.

장점은 단일 코드를 여러 부분으로 분할할 필요가 없다는 것입니다.이것은 당신이 파이썬으로 작성하면서 설계하는 일종의 계산이라면 좋습니다.이 초기 단계에서 추상화를 도입하면 속도가 느려질 수 있습니다.

이 접근 방식의 나쁜 점은 인터프리터/컴파일러 작성자가 일반적으로 예외가 예외적이라고 가정하고 그에 따라 예외를 최적화한다는 것입니다.

class ContinueI(Exception):
    pass


continue_i = ContinueI()

for i in ...:
    try:
        for j in ...:
            for k in ...:
                if something:
                    raise continue_i
    except ContinueI:
        continue

실수로 다른 예외를 무시할 위험이 없도록 이에 대한 특수 예외 클래스를 만듭니다.

완전히 다른 무언가.

저는 아직 다른 해결책이 있다고 확신합니다.

다른 언어에서는 루프에 레이블을 지정하고 레이블이 지정된 루프에서 분리할 수 있습니다.PYP(Python Enhancement Proposal) 3136은 Python에 이러한 기능을 추가할 것을 제안했지만 Guido는 이거부했습니다.

하지만 이 기능을 필요로 하는 복잡한 코드는 매우 드물기 때문에 저는 그것을 거부합니다.대부분의 경우 '반품'을 사용하는 등 클린 코드를 생성하는 기존 해결 방법이 있습니다.코드의 명확성이 리턴을 사용하는 것을 가능하게 하는 리팩터링으로 인해 어려움을 겪는 (희귀한) 실제 사례가 있지만, 이는 다음 두 가지 문제로 인해 상쇄됩니다.

  1. 언어의 복잡성이 영구적으로 증가했습니다.이는 모든 Python 구현뿐만 아니라 모든 소스 분석 도구와 언어에 대한 모든 설명서에도 영향을 미칩니다.

  2. 기능이 올바르게 사용되는 것보다 더 많이 남용되어 코드 선명도가 순으로 감소할 것으로 예상됩니다(이후 작성된 모든 파이썬 코드에서 측정됨).게으른 프로그래머들은 어디에나 있고, 당신이 알기도 전에 당신은 이해할 수 없는 코드를 손에 쥐고 있습니다.

그래서 여러분이 바라던 것이 운이 없기를 바란다면, 다른 답들 중 하나를 보세요. 좋은 선택들이 있기 때문입니다.

다음과 같은 방법을 사용할 수 있습니다.

for ii in range(200):
    restart = False
    for jj in range(200, 400):
        ...block0...
        if something:
            restart = True
            break
    if restart:
        continue
    ...block1...

우리는 무언가를 찾은 다음 내면의 반복을 멈추고자 합니다.저는 깃발 시스템을 사용합니다.

for l in f:
    flag = True
    for e in r:
        if flag==False:continue
        if somecondition:
            do_something()
            flag=False

이를 달성하는 가장 쉬운 방법 중 하나는 "continue"를 "break" 문으로 바꾸는 것이라고 생각합니다.

for ii in range(200):
 for jj in range(200, 400):
    ...block0...
    if something:
        break
 ...block1...       

예를 들어, 다음은 정확하게 진행되는 방식을 확인할 수 있는 쉬운 코드입니다.

for i in range(10):
    print("doing outer loop")
    print("i=",i)
    for p in range(10):
        print("doing inner loop")
        print("p=",p)
        if p==3:
            print("breaking from inner loop")
            break
    print("doing some code in outer loop")

이러한 문제를 해결하는 또 다른 방법은 사용하는 것입니다.Exception().

for ii in range(200):
    try:
        for jj in range(200, 400):
            ...block0...
            if something:
                raise Exception()
    except Exception:
        continue
    ...block1...

예:

for n in range(1,4):
    for m in range(1,4):
        print n,'-',m

결과:

    1-1
    1-2
    1-3
    2-1
    2-2
    2-3
    3-1
    3-2
    3-3

m =3일 때 m 루프에서 바깥쪽 n 루프로 점프한다고 가정합니다.

for n in range(1,4):
    try:
        for m in range(1,4):
            if m == 3:
                raise Exception()            
            print n,'-',m
    except Exception:
        continue

결과:

    1-1
    1-2
    2-1
    2-2
    3-1
    3-2

참조 링크: http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python

저는 그냥 이런 거 했어요.이에 대한 저의 해결책은 루프의 내부를 목록 이해로 대체하는 것이었습니다.

for ii in range(200):
    done = any([op(ii, jj) for jj in range(200, 400)])
    ...block0...
    if done:
        continue
    ...block1...

여기서 op는 ii와 jj의 조합에 작용하는 어떤 부울 연산자입니다.제 경우, 만약 어떤 작업이 사실로 돌아온다면, 저는 끝입니다.

이것은 실제로 코드를 함수로 나누는 것과 크게 다르지 않지만, 저는 "임의" 연산자를 사용하여 불리언 목록에서 논리적 OR을 수행하고 논리적 논리를 한 줄로 모두 수행하는 것이 흥미롭다고 생각했습니다.또한 함수 호출을 방지합니다.

외부 루프를 계속하는 가장 좋은 방법은 외부 루프 아래에 범위가 지정된 부울을 사용하여 내부 루프를 끊는 것입니다.그러나 사용 사례에 따라 내부 루프를 중단하지 않을 수도 있지만 내부 루프 내부에서 외부 루프를 계속 진행하면 외부 루프의 첫 번째 줄로 즉시 이동하고 내부 루프에서 추가 실행을 방지할 수 있습니다.그것이 제가 추가한 이유는break진술.

for i in range(0, 6):
    should_continue = False

    for f in range(1, i * 2):
        print(f"f = {f}")
        if (not (f % 1337) or not (f % 7)):
            print(f"{f} can be divided, continue outer loop")
            should_continue = True
            # leaves inner loop
            break

    if(should_continue): continue
    # Outer loop's code goes here
    print(f'Reached outer loop\ni = {i}')

이 접근 방식은 함수를 호출하고 가능한 결점을 처리하는 것을 방지합니다.함수 호출은 특히 게임의 경우 다소 비싼 작업으로 알려져 있습니다.이제 깊은 둥지가 있는 것을 상상해 보세요.for수백만 번 실행되는 루프를 함수 안에 감싸면 부드러운 경험이 되지 않습니다.

루프를 예외 블록 안에 감는 것도 좋지 않으며 기능보다 훨씬 느립니다.이는 Python이 예외 메커니즘을 트리거하고 나중에 런타임 상태를 복원하기 위해 많은 오버헤드가 필요하기 때문입니다. 예외는 예외적으로 사용되도록 설계되었습니다.이러한 점을 고려하여 다음과 같은 일부 CPU 최적화 작업도 수행할 수 있습니다.speculative execution예외 블록에는 적용되지 않아야 하며 적용되지 않을 수도 있습니다.

이 접근법에서 발견한 유일한 "문제"는break내부 루프 밖으로 한 번 점프하여 착지합니다.continue다시 한 번 더 뛰어오를 겁니다이것은 C나 JavaScript의 goto 문과는 대조적으로 조금 더 서툴지만 CPU의 클럭이나 인터프리터 구현만큼 빠르게 실행되는 하나의 추가 명령만 생성하기 때문에 성능에 가시적인 영향을 미치지 않습니다.

언급URL : https://stackoverflow.com/questions/1859072/python-continuing-to-next-iteration-in-outer-loop

반응형