가변 개수의 위치 인수를 받는 예제

def log(message, values):
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print("%s: %s" % (message, values_str))

log("My numbers are", [1, 2])
log("Hi there", [])             # 빈 리스트를 넘겨야 하는 것이 불편함

>>>
My numbers are: 1, 2
Hi there
  • 로그로 남길 값이 없을 때 빈 리스트를 넘겨야 하는 것이 불편함:
    • * 기호를 마지막 위치 파라미터 이름 앞에 붙이면 것으로 해결 가능
def log(message, *values):  # 첫 번째 파라미터인 message는 필수, 그 다음에 나오는 위치 인수는 몇 개든 선택적임
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print("%s: %s" % (message, values_str))

log("My numbers are", 1, 2)
log("Hi there")             # 호출하는 쪽만 수정

>>>
My numbers are: 1, 2
Hi there
  • * 연산자를 이용하여 리스트를 입력으로 사용할 수 있음
def log(message, *values):  # 첫 번째 파라미터인 message는 필수, 그 다음에 나오는 위치 인수는 몇 개든 선택적임
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print("%s: %s" % (message, values_str))

favorites = [7, 33, 99]
log("Favorite colors", *favorites)

>>>
Favorite colors: 7, 33, 99

가변 개수의 위치 인수를 받는 방법의 문제점

  • 가변 인수가 함수에 전달되기에 앞서 항상 튜플로 변환된다는 점
    • 함수를 호출하는 쪽에서 제너레이터에 * 연산자를 쓰면 제너레이터가 모두 소진할 때까지 순회됨
    • 결과로 만들어지는 튜플은 제너레이터로부터 생성되는 모든 값을 담게 됨
    • 따라서 메모리 문제가 발생할 수 있음
def my_generator():
    for i in range(10):
        yield i

def my_func(*args):
    print(args)

it = my_generator()     # 제너레이터 생성
my_func(*it)            # 제너레이터를 모두 순회하며 생성되는 값들이 전부 튜플로 변환: 메모리 문제 발생 가능

>>>
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  • 호출 코드를 모두 변경하지 않고서는 새 위치 인수를 추가할 수 없는 점
    • 인수 리스트의 앞쪽에 위치 인수를 추가하면 기존의 호출 코드가 수정 없이는 이상하게 동작함
def log(sequence, message, *values):
    if not values:
        print("%s: %s" % (sequence, message))
    else:
        values_str = ", ".join(str(x) for x in values)
        print("%s: %s: %s" % (sequence, message, values_str))
log(1, "Favorites", 7, 33)      # 새로운 용법은 OK
log("Favorite numbers", 7, 33)  # 오래된 용법은 제대로 동작하지 않음

>>>
1: Favorites: 7, 33
Favorite numbers: 7: 33     # sequence 인수를 받지 못했기 때문에 7을 message 파라미터로 사용
  • 이런 버그는 코드에서 예외를 일으키지 않고 계속 실행되므로 발견하기가 극히 여러움
  • *args를 받는 함수를 확장할 때 키워드 전용 인수를 사용해야 함
    • “WAY 21. 키워드 전용 인수로 명료성을 강요하자”

Go back to the List of Studies