5-3 반환값 다루기: return과 None 이해

5-3 반환값 다루기: return과 None 이해

← 목차로 돌아가기

썸네일

파이썬으로 코드를 작성하다 보면, 함수가 특정 작업을 마친 후 그 결과를 다른 곳에서 활용해야 할 때가 많습니다. 이때 함수가 결과를 ‘돌려주는’ 역할을 하는 것이 바로 반환값입니다. 이번 챕터에서는 함수의 핵심 기능 중 하나인 `return` 문과, 반환값이 없을 때 사용되는 특별한 값 `None`에 대해 자세히 알아보겠습니다.

핵심 요약

  • return 문: 함수가 특정 값을 계산하거나 처리한 후, 그 결과를 호출한 곳으로 되돌려주는 데 사용합니다.
  • 여러 값 반환: `return` 문으로 여러 값을 반환하면, 이 값들은 튜플 형태로 묶여 전달됩니다.
  • None: 파이썬에서 ‘값이 없음’을 나타내는 특별한 객체이며, 명시적인 `return` 문이 없는 함수는 자동으로 `None`을 반환합니다.
  • return과 print의 차이: `return`은 값을 돌려주어 재활용하게 하고, `print`는 단순히 화면에 출력만 할 뿐입니다.

함수는 왜 값을 돌려주어야 할까요? (`return`의 필요성)

함수는 특정 작업을 수행한 후 그 결과를 호출자에게 다시 전달하기 위해 `return` 문을 사용합니다.

우리는 지난 챕터에서 함수를 정의하고 호출하는 방법을 배웠습니다. 함수는 특정 작업을 캡슐화하여 코드의 재사용성을 높이는 강력한 도구입니다. 그런데 함수가 어떤 계산을 하거나 데이터를 처리한 후, 그 ‘결과’를 함수 밖의 다른 코드에서 사용해야 할 때가 생깁니다. 만약 함수가 계산만 하고 결과를 돌려주지 않는다면, 그 결과는 함수 내부에서만 존재하고 외부에서는 접근할 수 없게 됩니다.

예를 들어, 두 숫자를 더하는 함수를 만들었는데, 이 함수가 단순히 덧셈 결과를 화면에 출력하기만 한다고 가정해 봅시다. 이 경우, 그 결과값을 다른 변수에 저장하거나 다른 계산에 활용할 수 없게 됩니다. 이때 필요한 것이 바로 `return` 문입니다. `return`은 함수가 작업을 마치고 ‘짠! 내가 계산한 결과는 이거야!’라고 알려주는 것과 같습니다.

`return` 문 사용법 이해하기

return 키워드는 함수가 실행을 마친 후, 특정 값을 호출한 곳으로 되돌려주는 역할을 합니다. return 문이 실행되면 함수는 즉시 종료되고, 그 뒤에 오는 값이 반환됩니다. 만약 return 뒤에 아무 값도 명시하지 않으면 `None`이 반환됩니다.

예제를 통해 살펴보겠습니다. 두 숫자를 받아 합을 반환하는 함수입니다.

def add_numbers(a, b):
    sum_result = a + b
    return sum_result

# 함수 호출 및 반환값 저장
result = add_numbers(5, 3)
print(f"두 숫자의 합: {result}")

# 반환값을 다른 계산에 활용
another_result = result * 2
print(f"합의 두 배: {another_result}")

이 코드가 하는 일은 add_numbers 함수가 두 숫자를 더한 후 그 합을 반환하고, 이 반환된 값을 result 변수에 저장하여 다른 연산에 활용하는 것입니다.

저의 첫 파이썬 프로젝트에서 이 `return`과 `print`의 차이를 이해하지 못해 몇 시간을 헤맨 경험이 있습니다. 분명히 숫자가 출력되는데, 그 숫자를 가지고 다음 계산을 하려니 자꾸 `None` 타입 에러가 발생했죠. 돌이켜보면 당연한 실수였지만, 그때는 왜 안 되는지 정말 답답했습니다. 결국, 함수의 목적이 ‘결과를 돌려주는 것’이라면 반드시 `return`을 써야 한다는 것을 깨달았습니다. (2018년 제 첫 데이터 분석 스크립트 작성 시 경험)

여러 값 반환하기: 튜플 활용

파이썬 함수는 `return` 문 하나로 여러 값을 반환할 수 있으며, 이때 이 값들은 튜플 형태로 묶여 전달됩니다.

때로는 함수가 하나의 결과가 아니라 여러 개의 관련 정보를 동시에 반환해야 할 때가 있습니다. 파이썬에서는 `return` 문 뒤에 쉼표로 구분하여 여러 값을 나열하는 것만으로도 이를 쉽게 구현할 수 있습니다. 이때, 파이썬은 이 값들을 자동으로 튜플 형태로 묶어서 반환합니다.

def calculate_stats(numbers):
    min_val = min(numbers)
    max_val = max(numbers)
    avg_val = sum(numbers) / len(numbers)
    return min_val, max_val, avg_val # 세 값을 쉼표로 구분하여 반환

# 함수 호출 및 여러 반환값 받기
data = [10, 20, 30, 40, 50]
minimum, maximum, average = calculate_stats(data)

print(f"최솟값: {minimum}")
print(f"최댓값: {maximum}")
print(f"평균: {average}")

이 코드가 하는 일은 calculate_stats 함수가 숫자 리스트에서 최솟값, 최댓값, 평균값을 계산하여 세 값을 튜플 형태로 한 번에 반환하고, 호출하는 쪽에서 각각의 변수에 할당받아 사용하는 것입니다.

이렇게 여러 값을 반환하는 기능은 데이터 분석이나 통계 처리 함수를 작성할 때 매우 유용합니다. 예를 들어, 특정 데이터셋의 요약 통계를 한 번에 얻고 싶을 때, 각 통계량(평균, 중앙값, 표준편차 등)을 별도의 함수로 호출할 필요 없이 하나의 함수에서 모두 반환받아 처리할 수 있습니다. 이는 코드의 가독성을 높이고 불필요한 함수 호출을 줄여줍니다.

`None`은 무엇이며, 언제 사용될까요? (명시적 반환이 없을 때)

`None`은 파이썬에서 ‘값이 없음’을 나타내는 특별한 객체이며, 명시적인 `return` 문이 없는 함수는 자동으로 `None`을 반환합니다.

파이썬에서 `None`은 다른 프로그래밍 언어의 `null`과 비슷한 개념입니다. 어떤 변수에 할당된 값이 없음을 나타내거나, 함수가 특별히 반환할 유의미한 결과가 없을 때 사용됩니다. `None`은 고유한 데이터 타입(`NoneType`)을 가지며, `True`나 `False`처럼 파이썬의 예약어입니다.

`return` 문이 없는 함수의 동작

만약 함수 내부에 `return` 문이 명시적으로 없다면, 파이썬 인터프리터는 함수가 종료되는 시점에 암묵적으로 `return None`을 삽입합니다. 즉, 모든 함수는 반드시 어떤 값을 반환하며, 명시적으로 반환하지 않으면 `None`을 반환하는 것이 파이썬의 기본 동작입니다. 이는 함수 정의와 호출의 중요한 부분입니다.

def say_hello(name):
    print(f"안녕하세요, {name}님!")
    # 명시적인 return 문이 없습니다.

result = say_hello("이수진")
print(f"say_hello 함수의 반환값: {result}")
print(f"반환값의 타입: {type(result)}")

이 코드가 하는 일은 say_hello 함수는 단순히 인사말을 출력할 뿐, 명시적인 반환값이 없습니다. 따라서 이 함수를 호출한 후 반환값을 출력해보면 `None`이 나옵니다.

`None`을 활용하는 실용적인 방법

`None`은 단순히 ‘반환값 없음’을 의미하는 것을 넘어, 특정 조건이나 상태를 나타내는 데 유용하게 활용됩니다. 예를 들어, 어떤 값을 찾거나 특정 작업을 수행하는 함수에서, 해당 값을 찾지 못했거나 작업이 성공적으로 이루어지지 않았을 때 `None`을 반환하여 호출자가 후속 처리를 결정할 수 있도록 합니다.

def find_item_in_list(item_list, target_item):
    for item in item_list:
        if item == target_item:
            return item  # 항목을 찾으면 해당 항목 반환
    return None      # 항목을 찾지 못하면 None 반환

my_list = ["사과", "바나나", "오렌지"]

found_fruit = find_item_in_list(my_list, "바나나")
if found_fruit:
    print(f"찾은 과일: {found_fruit}")
else:
    print("원하는 과일을 찾지 못했습니다.")

not_found_fruit = find_item_in_list(my_list, "포도")
if not_found_fruit:
    print(f"찾은 과일: {not_found_fruit}")
else:
    print("원하는 과일을 찾지 못했습니다.")

이 코드가 하는 일은 find_item_in_list 함수가 목록에서 특정 항목을 찾아 반환하고, 없으면 `None`을 반환하도록 하여, 호출하는 쪽에서 이 `None` 여부를 확인하여 적절히 메시지를 출력하는 것입니다.

현업에서 데이터 분석 작업을 할 때, 특정 조건에 맞는 데이터가 없을 경우 `None`을 반환하는 함수를 자주 작성합니다. 예를 들어, `pandas` 데이터프레임에서 특정 조건을 만족하는 행을 찾아 반환하는데, 만약 해당하는 행이 없다면 `None`을 반환하도록 하여 이후 로직에서 `None` 여부를 확인하고 적절히 처리합니다. 이렇게 하면 불필요한 오류를 줄이고 코드의 안정성을 높일 수 있습니다. (2022년 회사 내부 보고서 자동화 툴 개발 경험)

흔한 실수와 해결법: `return`과 `print`의 차이

`return`은 함수의 결과를 호출자에게 돌려주어 다른 곳에서 사용할 수 있게 하는 반면, `print`는 단순히 콘솔에 내용을 출력하는 것이므로 이 둘을 혼동하지 않아야 합니다.

파이썬 초보자분들이 가장 흔히 하는 실수 중 하나가 함수에서 `return` 대신 `print`를 사용하는 것입니다. 두 기능 모두 화면에 어떤 내용을 ‘보여주는’ 것 같지만, 프로그래밍 관점에서 이 둘은 근본적으로 다릅니다.

print() 함수는 단순히 괄호 안의 내용을 화면(콘솔)에 출력하는 역할을 합니다. 하지만 출력된 값 자체는 변수에 저장되거나 다른 연산에 사용될 수 없습니다. 반면, return 문은 함수가 작업을 마치고 그 결과를 ‘돌려주는’ 역할을 하여, 이 결과값을 변수에 저장하거나 다른 함수의 인자로 전달하는 등 다양하게 활용할 수 있게 합니다.

# 실수 예시: print 사용
def multiply_and_print(a, b):
    print(f"계산 결과: {a * b}")

result_printed = multiply_and_print(3, 4) # 함수는 출력만 하고 None을 반환합니다.
print(f"함수 호출 후 result_printed 값: {result_printed}") # None이 출력됩니다.
# print(result_printed * 2) # TypeError: unsupported operand type(s) for *:'NoneType' and 'int'

# 올바른 예시: return 사용
def multiply_and_return(a, b):
    return a * b

result_returned = multiply_and_return(3, 4)
print(f"함수 호출 후 result_returned 값: {result_returned}") # 실제 계산 결과가 출력됩니다.
print(f"반환값을 활용한 추가 계산: {result_returned * 2}") # 24가 출력됩니다.

이 코드가 하는 일은 `multiply_and_print`는 콘솔에만 값을 출력하고 실제로는 `None`을 반환하여 이후 계산에 사용할 수 없습니다. 반면 `multiply_and_return`은 `return`을 사용하여 실제 계산 결과를 변수에 저장하고 활용하는 것을 보여줍니다.

함수에서 어떤 값을 함수 밖으로 전달하여 재사용하고 싶다면 반드시 `return`을 사용해야 한다는 것을 기억하세요. `print`는 디버깅이나 사용자에게 정보를 보여줄 때 유용하지만, 값의 ‘흐름’을 제어하는 역할은 하지 않습니다.

자주 묻는 질문 (FAQ)

Q1: 함수에서 `return`을 여러 번 사용할 수 있나요?

A1: 네, 사용할 수 있습니다. 하지만 `return` 문이 실행되면 함수는 즉시 종료됩니다. 따라서 여러 `return` 문이 있더라도, 특정 조건에 따라 그중 하나만 실행되고 함수는 종료됩니다. 예를 들어, `if-elif-else` 조건문 안에서 각 조건에 맞는 다른 값을 `return` 할 수 있습니다.

Q2: `return` 없이 함수를 종료하고 싶으면 어떻게 해야 하나요?

A2: `return` 뒤에 아무 값도 명시하지 않으면 됩니다. `return` 키워드만 단독으로 사용하면 함수는 즉시 종료되고 `None`을 반환합니다. 이는 특정 조건에서 함수를 일찍 종료해야 할 때 유용하게 쓰입니다.

Q3: `None`은 0이나 빈 문자열과 같은 의미인가요?

A3: 아닙니다. `None`은 ‘값이 없음’을 나타내는 고유한 객체입니다. 0은 숫자 0을, 빈 문자열(`”`)은 길이가 0인 문자열을 의미하는 반면, `None`은 어떤 데이터도 존재하지 않는 상태를 표현합니다. 이들은 각각 다른 타입과 의미를 가지므로 혼동하지 않도록 주의해야 합니다.

이번 챕터에서는 함수의 반환값에 대한 모든 것을 다루었습니다. `return`을 사용하여 함수가 계산한 결과를 효율적으로 활용하고, `None`의 의미와 사용법을 정확히 이해하는 것은 견고한 파이썬 코드를 작성하는 데 필수적인 지식입니다. 이제 여러분의 함수들이 더욱 유연하고 강력해질 것입니다. 다음 챕터에서는 지역 변수와 전역 변수의 스코프 개념을 통해 변수가 코드 어디까지 영향을 미치는지 살펴보겠습니다.

참고 자료

  1. [1] Python 공식 튜토리얼 — 제어 흐름 도구와 함수 정의 — https://docs.python.org/ko/3/tutorial/controlflow.html
  2. [2] Python 용어집 — https://docs.python.org/ko/3/glossary.html

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다