제너레이터_안에서_throw상태_변화하지_마라

매일 공부(ML)·2022년 6월 27일
0

이어드림

목록 보기
86/146

throw 메서드

  • 제너레이터 안에서 throw 호출

  • yield로 평소처럼 실행

  • throw가 제공한 Exception다시 던진다.


#throw 메소드에 의존하는 제너레이터 타이머
class Reset(Exception):
    pass

def timer(period):
    current = period
    while current:
        current -=1
        try:
            yield current
        except Reset:
            current = period
#타이머 코드
def check_for_reset():
    #외부 이벤트 폴링
    ...

def announce(remaining):
    print(f'{remaining} 틱 남음')

def run():
    it = timer(4)
    while True:
        try:
            if check_for_reset():
                current =  it.throw(Reset())
            else:
                current = next(it)
        except StopIteration:
            break
        else:
            announce(current)

run()

위의 코드 단점

  • 작동은 잘하지만 가독성이 너무 떨어진다.

  • 각 내포 단계별로 throw or 호출로 결정되는데 코드 잡음이 많다.


해결책: iterlabel class 사용

class Timer:
    def __init__(self, period):
        self.current = period
        self.period = period

    def  reset(self):
        self.current = self.period

    def __iter__(self):
        while self.current:
            self.current -=1
            yield self.current

def run():
    timer = Timer(4)
    for current in timer:
        if check_for_reset():
            timer.reset()
        announce(current)

run()

Summary

  • throw메서드를 사용하면 제너레이터가 마지막으로 실행한 yield 식의 위치에서 예외가 다시 발생할 수 있다

  • throw를 사용하면 가독성이 나빠지게 되어서 예외를 잡아내고 다시 발생시키는데 준비 코드가 필요하고 내포 단계가 깊어진다.

  • 제너레이터에서 예외적인 동작을 제공하는 더 나은 법은 iter메서드를 구현하는 클래스를 사용해서 예외적인 경우 상태 전이

profile
성장을 도울 아카이빙 블로그

0개의 댓글