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

파이썬 함수는 어떻게 값을 반환(return)하고 양도(yield)할까?

return 문의 기본 동작

파이썬에서 return 문은 함수의 실행을 종료하고 호출자(caller)에게 값을 되돌려주는 역할을 합니다. 함수는 본래 입력값을 받아 어떤 결과를 돌려주는 것이 목적이므로, return 문이 실행되는 순간 함수의 실행은 즉시 중단됩니다. 설령 return 문이 함수의 마지막 줄이 아니더라도 마찬가지입니다.

이렇게 값을 반환하는 함수는 흔히 '결실 있는 함수(fruitful functions)'라고 부르기도 합니다.

예제

def sum(a, b):
    return a + b

result = sum(5, 16)
print(result)

출력 결과

21

위 코드에서 sum(5, 16)을 호출하면 두 인수가 더해진 값인 21이 호출자에게 반환됩니다.

제너레이터(Generator)란?

제너레이터는 리스트나 튜플과 같은 반복 가능한(iterable) 객체입니다. 하지만 딱 한 번만 순회할 수 있다는 점이 다릅니다. 그 이유는 제너레이터가 모든 값을 메모리에 미리 저장해 두지 않고, 필요할 때마다 값을 그때그때 생성하기(on the fly) 때문입니다.

예제

mygenerator = (x * x for x in range(4))

for i in mygenerator:
    print(i)

출력 결과

0
1
4
9

제너레이터는 한 번 소진되면 재사용할 수 없습니다. 따라서 동일한 제너레이터에 대해 두 번째로 for 루프를 실행할 수 없습니다. 내부적으로 0을 계산한 뒤에는 그 값을 버리고, 이어서 1, 4를 계산한 후 마지막으로 9를 계산하기 때문입니다.

yield 키워드

yield는 return과 비슷하게 사용되는 키워드지만, 결정적인 차이가 있습니다. yield를 포함한 함수는 단순히 값을 하나 돌려주고 끝나는 것이 아니라 제너레이터 객체 자체를 반환합니다.

반환된 제너레이터가 만들어내는 값은 다음과 같이 next() 함수를 통해 하나씩 접근할 수 있습니다.

예제

def createGenerator():
    for i in range(4):
        yield i * i   # 이 코드가 제너레이터를 생성합니다

mygenerator = createGenerator()
print(mygenerator)   # mygenerator는 하나의 객체입니다!

print(next(mygenerator))
print(next(mygenerator))
print(next(mygenerator))
print(next(mygenerator))
print(next(mygenerator))

출력 결과

<generator object createGenerator at 0xb71e27fc>
0
1
4
9
Traceback (most recent call last):
  File "yieldgen1.py", line 12, in <module>
    print(next(mygenerator))
StopIteration

동작 원리 상세 설명

위 예제에서 yield 문은 createGenerator가 일반적인 함수처럼 작동하지 않게 만듭니다. 대신 이 함수를 호출하면 새로운 제너레이터 객체가 생성되며, mygenerator는 오직 한 번만 사용할 수 있습니다.

next(mygenerator) 명령을 호출할 때마다 값이 하나씩 계산되어 꺼내집니다. 첫 번째 호출에서는 0을 계산해 반환한 뒤 실행 위치와 상태를 그대로 유지하고, 두 번째 호출에서는 1, 세 번째는 4, 네 번째는 9를 계산합니다. 그리고 다섯 번째 호출 시점에는 더 이상 남아 있는 요소가 없으므로 StopIteration 예외가 발생합니다.

이러한 특성 덕분에 제너레이터는 전체 데이터를 메모리에 올리지 않고도 대용량 데이터 집합을 효율적으로 순차 처리할 수 있는 강력한 도구가 됩니다.