함수 좀 더 파헤치기
인수 전달 시 매개변수 지정
함수에 전달되는 인수는 함수 선언 시 명시한 매개변수의 순서에 따라 언제나 순서대로 저장됩니다.
즉, 다음 예제와 같이 선언된 함수를 호출할 때 전달받은 첫 번째 인수는 언제나 매개변수 a에 저장되며, 두 번째 인수는 언제나 매개변수 b에 저장되는 것입니다.
예제
def sub(a, b):
print(a - b)
이때 전달받은 인수가 저장되는 매개변수를 직접 지정하고 싶다면, 다음 예제의 7번 라인처럼 함수를 호출할 때 대입 연산자(=)를 사용하여 인수가 저장될 매개변수를 직접 지정하면 됩니다.
실행 결과
-1
-1
1
위 예제의 5번과 6번 라인은 같은 의미이며, 7번 라인에서는 인수가 전달되는 순서를 매개변수를 지정하여 직접 변경하고 있습니다.
따라서 결과값이 다르게 출력되는 것을 확인할 수 있습니다.
매개변수의 기본값 설정(default parameters)
우리는 앞서 함수의 기초에 대해 살펴볼 때 함수를 호출할 때 선언 시 명시된 매개변수의 개수보다 적거나 많은 인수를 전달할 경우 TypeError가 발생한다고 배웠습니다.
하지만 함수를 선언할 때 미리 매개변수의 기본값을 설정해 놓으면, 함수 호출 시 전달받지 못한 인수에 대해서는 설정해 놓은 기본값으로 자동 초기화할 수 있습니다.
예제
def total(a, b=5, c=10):
print(a + b + c)
total(1)
total(1, 2)
total(1, 2, 3)
# total(b=2, c=3)
# total(1, 2, 3, 4)
실행 결과
16
13
6
위 예제의 5번 라인에서는 total() 함수를 호출하면서 인수를 하나만 전달하고 있습니다.
이때 인수로 전달받은 1은 매개변수 a에 저장되며, 전달받지 못한 매개변수 b와 c의 값은 각각 기본값인 5와 10을 사용하여 초기화하게 됩니다.
6번 라인에서는 인수로 전달받은 1과 2를 각각 매개변수 a와 b에 저장하고, 전달받지 못한 매개변수 c의 값만을 10으로 초기화하여 사용하게 됩니다.
7번 라인에서는 함수 호출 시 3개의 인수를 모두 전달받았으므로, 기본값을 사용하지 않고 전달받은 인수의 값으로만 매개변수를 초기화하게 됩니다.
하지만 매개변수의 기본값을 설정해도 8번과 9번 라인처럼 기본값을 설정하지 않은 매개변수에 인수를 전달하지 않거나, 매개변수의 수보다 더 많은 인수를 전달하여 함수를 호출하면 여전히 TypeError가 발생합니다.
이처럼 매개변수의 기본값은 매우 편리하게 활용할 수 있지만, 다음과 같이 사용할 수는 없습니다.
예제
def total(a=5, b, c=10):
print(a + b + c)
total(1)
함수에 전달되는 인수는 함수 선언 시 명시한 매개변수의 순서에 따라 언제나 순서대로 저장됩니다.
위의 예제에서 total() 함수를 호출할 때 전달받은 인수 1은 매개변수 b가 아닌 매개변수 a에 저장되며, 따라서 매개변수 b에 저장할 인수가 없기 때문에 이 예제는 SyntaxError를 발생시킵니다.
이처럼 매개변수의 기본값 설정은 매개변수의 목록에서 항상 오른쪽부터 차례대로 명시되어야만 합니다.
가변 매개변수(variable parameters)
함수를 실제로 호출할 때 몇 개의 인수가 전달될지 미리 알 수 없다면, 사용자가 직접 매개변수의 개수를 정할 수 있도록 선언할 수 있습니다.
가변 매개변수는 다음과 같이 매개변수명 앞에 별(*) 기호를 추가하여 선언합니다.
문법
def 함수명(*매개변수명):
실행할 코드1
실행할 코드2
⦙
이렇게 선언된 가변 매개변수에는 함수가 호출될 때 전달된 모든 인수가 튜플(tuple)의 형태로 저장됩니다.
가변 매개변수는 다음 예제처럼 함수 내에서 반복문 등을 통해 자유롭게 접근하여 사용할 수 있습니다.
예제
def add(*paras):
print(paras)
total = 0
for para in paras:
total += para
return total
print(add(10))
print(add(10, 100))
print(add(10, 100, 1000))
실행 결과
(10,)
10
(10, 100)
110
(10, 100, 1000)
1110
위의 예제처럼 가변 매개변수를 사용하면 함수를 호출할 때 전달받는 인수의 개수에 상관없이 일정한 동작을 수행하는 함수를 작성할 수 있습니다.
이때 가변 매개변수로 딕셔너리를 사용하려면, 하나의 별(*) 기호가 아닌 두 개의 별(**) 기호를 사용하여 선언해야 합니다.
예제
def print_map(**dicts):
for item in dicts.items():
print(item)
print_map(하나=1)
print_map(one=1, two=2)
print_map(하나=1, 둘=2, 셋=3)
실행 결과
('하나', 1)
('one', 1)
('two', 2)
('하나', 1)
('둘', 2)
('셋', 3)
여러 개의 결괏값 반환하기
함수에서 return 문을 통해 반환할 수 있는 결괏값은 언제나 하나입니다.
따라서 두 개 이상의 결괏값을 반환하고 싶다면 튜플을 사용해야 합니다.
예제
def arith(a, b):
add = a + b
sub = a - b
return add, sub
i, j = arith(10, 1)
print(i)
print(j)
실행 결과
11
9
위 예제의 4번 라인처럼 반환하고 싶은 모든 결괏값을 하나의 튜플로 만들어 반환할 수 있습니다.
이렇게 반환된 결괏값은 7번 라인처럼 튜플의 언패킹을 통해 각각의 변수에 곧바로 대입하여 사용할 수 있습니다.
람다(lambda)
람다(lambda)란 간단한 함수의 선언과 호출을 하나의 식으로 간략히 표현한 것입니다.
이러한 람다는 일반 함수와는 달리 이름을 가지지 않으며, map()이나 filter() 함수와 같이 함수 자체를 인수로 전달받는 함수에서 자주 사용됩니다.
파이썬에서는 lambda 키워드를 사용하여 다음과 같이 람다를 정의할 수 있습니다.
문법
lambda 매개변수1, 매개변수2, ...: 매개변수를 이용한 표현식
실행 결과
3
3
위 예제의 1번부터 4번 라인까지의 함수의 선언과 호출 과정 전부를 6번 라인처럼 람다를 사용하면 단 한 줄로 줄여서 표현할 수 있습니다.
단, add() 함수는 선언된 이 후에 프로그램 내에서라면 언제라도 또다시 호출할 수 있지만, 람다는 단 한 번밖에 사용할 수 없는 차이점을 가집니다.
이처럼 람다는 단 한 번만 사용할 함수를 간단하게 선언하고 호출할 때 매우 유용하게 사용할 수 있습니다.