본문 바로가기
파이썬/문법

Python | for..else 문법으로 이중 for loop을 continue하기

by 하우론 2022. 12. 29.

for..else

프로그램을 짜다 보면 for loop이 정상적으로 실행됐는지 중간에 break 됐는지 확인해야 할 상황이 생긴다. 보통은 is_broken 등의 플래그를 두는 식으로 짠다. 하지만 파이썬은 for..else라는 특이한 문법을 지원한다. 만약 for loop이 성공적으로 실행됐다면 else를 실행한다.

# w/o for..else
is_broken = False
for i in range(100):
    if not testcase(i):
        print(f'{i} failed')
        is_broken = True
        break
if not is_broken:
    print('all passed!')


# w/ for..else
for i in range(100):
    if not testcase(i):
        print(f'{i} failed')
        break
else:
    print('all passed!')

만약 모든 testcase가 성공한다면 all passed!라고 뜰 것이고 만약 i에서 실패한다면 failed가 뜨게 될 것이다.

 

처음엔 살짝 혼란스러울 순 있어도 익숙해지면 오히려 가독성이 좋다.

바깥 for loop 생략하기 (Continuing to the next outer iteration within the inner loop)

# problem scenario
for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue-ii-loop  # 만약 여기 break을 넣게 되면 block1이 실행 된다. 그러지 않았으면 좋겠는 상황이다.
    ...block1...

우리가 원하는 건 jj loop을 도는 동안 한번도 something에 걸리지 않아야 block1을 실행하는 것이다. 위는 pseudo-code이다. Inner loop 안에서 outer loop를 continue 시켜주기 위한 예약어는 없지만 for..else를 이용해 대충 구현이 가능하다.

 

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

위와 같이 짜게 되면 something에 걸리는 순간 break 되고 block1이 실행되지 않는다.

 

출처

https://stackoverflow.com/questions/1859072/python-continuing-to-next-iteration-in-outer-loop#comment1755590_1859072

 

Python: Continuing to next iteration in outer loop

I wanted to know if there are any built-in ways to continue to next iteration in outer loop in python. For example, consider the code: for ii in range(200): for jj in range(200, 400): ...

stackoverflow.com

예시

나 같은 경우는 테스트 케이스를 위한 로그 파일들을 불러오면서 기록을 해놓고 파일들이 다 있는 경우에만 테스트 케이스를 실행하는 식으로 구현 할 때 사용헀다.

if args.test:
    for p_case_dir in Path('test/logs').glob('**/*'):
        for obj in ['node', 'job']:
            p_obj = (p_case_dir / obj).with_suffix('.log')
            if p_obj.is_file():
                with p_obj.open() as f:
                    strings[f'{obj}_strings'] = f.read().strip().split('\n\n')
            else:
                break
        else:  # no break
            print(p_case_dir.name)
            SlurmTresVisualizer(**strings)