Programming

파이썬 : 외부 루프에서 다음 반복으로 계속

procodes 2020. 7. 28. 22:04
반응형

파이썬 : 외부 루프에서 다음 반복으로 계속


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

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

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


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()

단점은 이전에 범위에 있던 일부 변수를 해당 새 함수에 전달해야 할 수도 있다는 것입니다. 매개 변수로 매개 변수를 전달하고 객체에서 인스턴스 변수를 만들거나 (이 함수에 맞는 새 객체를 만드는 경우) 전역 변수, 단일 톤 (ehm, ehm)을 지정할 수 있습니다.

또는 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

이를 위해 특별한 예외 클래스를 생성하여 실수로 다른 예외를 침묵시킬 위험이 없도록하십시오.

완전히 다른 것

나는 여전히 다른 해결책이 있다고 확신합니다.


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

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


In other languages you can label the loop and break from the labelled loop. Python Enhancement Proposal (PEP) 3136 suggested adding these to Python but Guido rejected it:

However, I'm rejecting it on the basis that code so complicated to require this feature is very rare. In most cases there are existing work-arounds that produce clean code, for example using 'return'. While I'm sure there are some (rare) real cases where clarity of the code would suffer from a refactoring that makes it possible to use return, this is offset by two issues:

  1. The complexity added to the language, permanently. This affects not only all Python implementations, but also every source analysis tool, plus of course all documentation for the language.

  2. My expectation that the feature will be abused more than it will be used right, leading to a net decrease in code clarity (measured across all Python code written henceforth). Lazy programmers are everywhere, and before you know it you have an incredible mess on your hands of unintelligible code.

So if that's what you were hoping for you're out of luck, but look at one of the other answers as there are good options there.


I think you could do something like this:

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

Another way to deal with this kind of problem is to use Exception().

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

For example:

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

result:

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

Assuming we want to jump to the outer n loop from m loop if m =3:

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

result:

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

Reference link:http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python


I think one of the easiest ways to achieve this is to replace "continue" with "break" statement,i.e.

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

For example, here is the easy code to see how exactly it goes on:

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")

We want to find something and then stop the inner iteration. I use a flag system.

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

I just did something like this. My solution for this was to replace the interior for loop with a list comprehension.

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

where op is some boolean operator acting on a combination of ii and jj. In my case, if any of the operations returned true, I was done.

This is really not that different from breaking the code out into a function, but I thought that using the "any" operator to do a logical OR on a list of booleans and doing the logic all in one line was interesting. It also avoids the function call.

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

반응형