Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python return vs yield: 언제 yield를 사용해야 할까?

```html

결론부터 말하면, 프로그램의 실행 흐름이 return 문에 도달하면 해당 함수의 실행이 그 시점에서 완전히 종료되며, 그 뒤에 남아 있는 문장들은 더 이상 실행되지 않습니다.

반면 yield의 경우, 실행 흐름이 yield 문에 도달하면 함수의 실행이 일시적으로 멈추고(pause), 이후 필요할 때 함수 내 나머지 문장들을 이어서 계속 실행할 수 있습니다.

지금부터 두 문장의 동작 방식을 하나씩 자세히 살펴보겠습니다.

yield란?

함수 안에서 yield 문을 사용하면 그 함수는 제너레이터(generator) 함수가 되며, 루프에서 반복적으로 사용할 수 있습니다. 함수가 실행되는 도중 yield 문이 실행되면, yield 뒤에 있는 값이 함수를 호출한 루프로 전달됩니다. 그리고 루프가 다음 번 반복될 때, 함수는 처음부터 다시 시작하는 것이 아니라 마지막으로 실행된 yield 문 바로 다음 지점부터 이어서 실행됩니다.

def func():
    yield 1
    yield 2
    yield 3

for num in func():
    print(num * num)

실행 결과

1
4
9

위 프로그램에서 함수를 호출하는 루프는 func() 함수가 끝날 때 함께 종료됩니다. 즉, 함수의 끝에 도달하거나 return 문을 만나면 루프도 종료됩니다.

다만, 동일한 제너레이터 함수를 사용하는 새로운 루프는 함수를 처음부터 다시 실행한다는 점에 유의해야 합니다.

return이란?

  • return 문은 함수의 실행을 중단하고, 선택적으로 호출자에게 값을 반환하는 데 사용됩니다. return만 있고 yield가 없는 함수는 앞선 yield 예제처럼 루프에서 사용할 수 없습니다.
  • 이미 한 번 실행된 적이 있는 함수를 다시 호출하면, 함수는 항상 처음부터 실행을 시작합니다. yield와 달리 이전 실행 위치나 변수 상태를 기억하지 못합니다.

return과 yield 비교 정리

구분returnyield
실행 흐름함수 실행이 완전히 종료됨실행이 일시 중지된 후 재개 가능
상태 유지이전 상태를 기억하지 못함마지막 실행 위치와 변수 상태를 유지
반복문 활용불가능가능 (제너레이터 객체)
메모리 사용전체 결과를 한 번에 반환값을 하나씩 생성하여 메모리 효율적

return과 yield, 언제 무엇을 사용해야 할까?

일반적으로 어떤 시퀀스(연속된 값들)를 순회(iterate)하고 싶지만, 리소스 제약이 있거나 전체 시퀀스를 메모리에 한꺼번에 저장하고 싶지 않은 경우에는 yield를 사용하는 것이 좋습니다. 그 외의 경우에는 return 문을 사용하면 됩니다.

이번에는 yield를 사용해 정수의 제곱을 계속 생성하는 예제를 살펴보겠습니다.

def Square():
    i = 1
    # 제곱 값을 계속 생성하는 무한 루프
    while True:
        yield i * i
        i += 1  # 다음 실행은 이 지점부터 재개됩니다

for num in Square():
    if num > 100:
        break
    print(num)

실행 결과

1
4
9
16
25
36
49
64
81
100

위 예제처럼 yield를 사용하면 무한히 값을 생성하는 함수도 만들 수 있습니다. 값이 필요한 시점에 하나씩 생성되므로(lazy evaluation), 100보다 커지는 순간 루프를 빠져나오기만 하면 되고, 불필요한 연산과 메모리 낭비가 발생하지 않습니다.

한 가지 주의할 점은, yield 문은 일반적으로 try ... finally 블록의 try 절 안에서 사용하지 않는 것이 좋다는 것입니다. 제너레이터가 다시 재개된다는 보장이 없기 때문에, finally 블록이 실제로 실행된다는 보장도 없기 때문입니다.