2023-07-30 16:40:06
728x90
728x90

함수와 관련된 용어를 몇 가지 정리해 보자. 함수를 사용하는 것을 함수를 호출한다고 표현한다. 함수를 호출할 때는 괄호 내부에 여러가지 자료를 넣게 되는데, 이러한 자료를 매개변수 라고 부른다. 마지막으로 함수를 호출해서 최종적으로 나오는 결과를 리턴값이라고 부른다.

 

함수의 기본

함수는 한마디로 '코드의 집합'이다. 함수를 생성하는 기본 형태는 다음과 같다.

def 함수 이름():
    문장
def print_3_times():
    print("안녕하세요")
    print("안녕하세요")
    print("안녕하세요")
print_3_times()

 

함수에 매개변수 만들기

비주얼 스튜디오 코드에서 함수를 사용하면서 자동완성 기능이 작동하는 것을 본적이 있을 것이다. 예를 들어 print() 함수를 작성할떄 print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)와 같이 괄호 안에 많은 것들이 있다. 이러한 것들을 모두 매개변수라고 부른다. 매개변수는 다음과 같이 함수를 생성할 때 괄호 내부에 식별자를 입력해서 만든다.

def 함수 이름(매개변수, 매개변수, ...):
    문장
def print_n_times(value, n):
    for i in range(n):
        print(value)
print_n_times("안녕하세요", 5)

함수의 괄호 내부에 value와 n이라는 식별자를 입력했다. 이렇게 입력하면 이는 매개변수가 된다. 이렇게 매개변수를 만들면 함수를 호출할 때 값을 입력해서 함수쪽으로 전달할 수 있다.

 

현재 코드에서는 print_n_times("안녕하세요", 5) 형태로 함수를 호출하므로 매개변수 value에는 "안녕하세요"가 들어가고, 매개변수 n에는 5가 들어간다. 따라서 코드를 실행하면 "안녕하세요"를 5번 출력한다.

 

가변 매개변수

앞서 살펴본 함수는 함수를 선언할 때의 매개변수와 함수를 호출할 때의 매개변수가 같아야 했다. 적어도 안 되고 많아도 안 된다. 그러나 가장 많이 사용해 왔던 print() 함수는 매개변수를 원하는 만큼 입력할 수 있었다. 이처럼 매개변수를 원하는 만큼 받을 수 있는 함수를 가변 매개변수 함수라고 부르는데, 여기에서 가변 매개변수란 매개변수 개수가 변할 수 있다는 의미이다.가변 매개 변수 함수는 다음과 같은 형태로 만든다.

def 함수 이름(매개변수, 매개변수, ..., *가변 매개변수):
    문장

 

가변 매개변수를 사용할 때는 다음과 같은 제약이 있다.

 

1. 가변 매개변수 뒤에는 일반 매개변수가 올 수 없다.

2. 가변 매개변수는 하나만 사용할 수 있다.

 

이러한 제약이 없으면 가변 매개변수가 어디부터 어디까지인지 알 수 없기 때문에 만들어진 규칙이다. 가변 매개변수 함수를 만들어 보자.

 

def print_n_times(n, *values):
    #n번 반복
    for i in range(n):
        #values는 리스트처럼 활용
        for value in values:
            print(value)
            # 단순한 줄바꿈
            print()
#함수를 호출
print_n_times(3, "안녕하세요", "즐거운", "파이썬 프로그래밍")

가변 매개변수 뒤에는 일반 매개변수가 올 수 없다고 했다. 만약 print_n_times("안녕하세요", "즐거운", "파이썬 프로그래밍", 3)처럼 사용할 수 있다고 하면 어디까지가 가변 매개변수고, 어디가 매개변수 n인지 구분하기 힘들다. 따라서 파이썬 프로그래밍 언어는 내부적으로 가변 매개변수 뒤에 일반 매개변수가 오지 못하게 막은것이다. 그래서 매개변수 n을 앞으로 옮기고 매개변수 *values를 뒤로 밀었다. 가변 매개변수 *values는 리스트처럼 사용하면 된다. 예제에서는 반복문을 두 번 사용해서 쭉 출력하게 만들었다.

 

기본 매개변수

print() 함수의 자동 완선 기능으로 나오는 설명을 다시 적어보면 다음과 같다.

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

가장 앞에 있는 value가 바로 '가변 매개변수'이다. 앞에서 가변 매개변수 뒤에는 일반 매개변수가 올 수 없다고 했는데 매개변수가 왔다. 그런데 뭔가 특이하게 '매개변수=값'형태로 되어있다. 이는 기본 매개변수라고 부르며, 매개변수를 입력하지 않았을 경우 매개변수에 들어가는 기본값이다. 기본 매개변수도 다음과 같은 제약이 있다.

 

※ 기본 매개변수 뒤에는 일반 매개변수가 올 수 없다.

 

def print_n_times(value, n = 2):
    # n번 반복
    for i in range(n):
        print(value)
#함수를 호출
print_n_times("안녕하세요")

매개변수 n을 n = 2라는 형태로 입력했다. n을 입력하지 않을 경우 기본값이 2로 들어간다. 그래서 코드를 실행하면 "안녕하세요"라는 문자열을 두 번 출력한다.

 

키워드 매개변수

지금까지의 설명을 보면서 가변 매개변수와 기본 매개변수 둘을 같이 써도 되는지 상황을 나누어 살펴보자.

 

※ 기본 매개변수가 가변 매개변수보다 앞에 올 때

기본 매개변수가 가변 매개변수보다 앞에 올때는 기본 매개변수의 의미가 사라진다. 다음 코드의 실행 결과를 예측해 보자. n에는 무엇이 들어갈까?

def print_n_times(n = 2, *values):
    for i in range(n):
        #values는 리스트처럼 활용
        for value in values:
            print(value)
        #단순한 줄바꿈
        print()
#함수를 호출
print_n_times("안녕하세요", "즐거운", "파이썬 프로그래밍")

매개변수가 순서대로 입력되므로 n에는 "안녕하세요"가 들어가고, values에는 ["즐거운", "파이썬 프로그래밍"]이 들어온다. 그런데 range() 함수의 매개변수에는 숫자만 들어올수 있으므로 오류가 발생한다.

 

※ 가변 매개변수가 기본 매개변수보다 앞에 올 때

그러면 반대로 가변 매개변수가 기본 매개변수보다 앞에 올 때는 어떻게 될까? 다음 코드의 실행 결과를 예측해 보자.

def print_n_times(*values,n = 2):
    for i in range(n):
        #values는 리스트처럼 활용
        for value in values:
            print(value)
        #단순한 줄바꿈
        print()
#함수를 호출
print_n_times("안녕하세요", "즐거운", "파이썬 프로그래밍", 3)

다음과 같은 두가지 예측을 할 수있다.

 

1. ["안녕하세요", "즐거운", "파이썬 프로그래밍"]을 세번 출력한다.

2. ["안녕하세요", "즐거운", "파이썬 프로그래밍", 3]을 두번 출력한다.

 

코드를 실행하면 두 번째 예상대로 실행된다. 가변 매개변수가 우선되는 것이다.

파이썬 프로그래밍 언어는 이런 상황에 대비해서 키워드 매개변수라는 기능을 만들었다.

 

※ 키워드 매개변수

매개변수 이름을 지정해서 입력하는 매개변수를 키워드 매개변수라고 부른다.

def print_n_times(*values,n = 2):
    for i in range(n):
        #values는 리스트처럼 활용
        for value in values:
            print(value)
        #단순한 줄바꿈
        print()
#함수를 호출
print_n_times("안녕하세요", "즐거운", "파이썬 프로그래밍", n = 3) #n = 3은 키워드 매개변수이다.

 

※ 기본 매개변수 중에서 필요한 값만 입력하기

키워드 매개변수는 기본 매개변수들로 구성된 함수에서도 많이 사용된다.

def test(a, b = 10, c = 100):
    print(a + b + c)
    # 1) 기본 형태 (결과값 = 60)
    test(10, 20, 30)
    # 2) 키워드 매개변수로 모든 매개변수를 지정한 형태 (결과값 = 310)
    test(a = 10, b = 100, c = 200)
    # 3) 키워드 매개변수로 모든 매개변수를 마구잡이로 지정한 형태  (결과값 = 310)
    test(c = 10, a = 100, b = 200)
    # 4) 키워드 매개변수로 일부 매개변수만 지정한 형태  (결과값 = 220)
    test(10, c = 200)

 

리턴

함수의 결과를 리턴값(return value)이라고 부른다. 왜 '리턴'이라고 하는 걸까? 하나씩 살펴보자.

 

※ 자료 없이 리턴하기

함수 내부에서는 return 키워드를 사용할 수 있다. 이 키워드는 함수를 실행했던 위치로 돌아가라는 뜻으로, 함수가 끝나는 위치를 의미한다.

#함수를 정의한다.
def return_test():
    print("A 위치입니다.")
    return                #리턴 한다.
    print("B 위치입니다.")
#함수를 호출
return_test()

함수 내부에서 출력을 두 번 사용했는데 중간에 return 키워드가 들어 있다. return 키워드는 함수를 실행했던 위치로 돌아가라는 의미와 함수를 여기서 끝내라는 의미를 가지고 있다고 했다. 따라서 return 키워드를 만나는 순간 함수가 종료되어 결과적으로 "A 위치입니다."만 출력하고 프로그램이 종료된다.

 

※ 자료와 함게 리턴하기

리턴 뒤에 자료를 입력하면 자료를 가지고 리턴한다. 다음은 return 키워드 뒤에 100이라는 숫자를 입력한 코드이다. 함수의 실행 결과로 100이 출력되는 것을 확인할 수 있다.

#함수를 정의
def return_test():
    return 100
#함수를 호출
value = return_test()
print(value)

 

※ 아무것도 리턴하지 않기

그렇다면 아무것도 리턴하지 않았을 때는 어떻게 출력될까? None을 출력한다. None은 파이썬에서 '없다'라는 의미이다.

#함수를 정의
def return_test():
    return
#함수를 호출
value = return_test()
print(value)
#함수를 정의
def return_test():
    return
#함수를 호출
value = return_test() # 리턴할때 아무것도 가져가지 않아 value의 값은 None이 된다.
print(value)

 

기본적인 함수의 활용

리턴과 관련된 구문의 형식을 간단하게 살펴보았다. 구문만 봐서는 어떻게 활용하는지 잘 이해되지 않을 것이다. 일반적으로 함수는 다음과 같이 값을 만들어 리턴하는 형태로 많이 사용한다.

def 함수(매개변수):
    변수 = 초깃값
    # 여러 가지 처리
    # 여러 가지 처리
    # 여러 가지 처리
    # return 변수

 

※ 범위 내부의 정수를 모두 더하는 함수

# 함수를 선언
def sum_all(start, end):
    # 변수 선언
    output = 0
    #반복문을 돌려 숫자를 더한다.
    for i in range(start, end + 1):
        output += i
    return output
#함수를 호출
print("0 to 100: ", sum_all(0, 100)) # 결과값 = 0 to 100: 5050
print("0 to 1000: ", sum_all(0, 1000)) # 결과값 = 0 to 1000: 500500
print("50 to 100: ", sum_all(50, 100)) # 결과값 = 50 to 100: 3825
print("500 to 1000:", sum_all(500, 1000)) # 결과값 = 500 to 1000: 375750

 

※ 기본 매개변수와 키워드 매개변수를 활용해 범위의 정수를 더하는 함수

# 함수를 선언
def sum_all(start = 0, end = 100, step = 1):
    # 변수를 선언
    output = 0
    # 반복문을 돌려 숫자를 더한다
    for i in range(start, end + 1, step):
        output += i
    #리턴한다.
    return output
#함수를 호출
print("A.", sum_all(0, 100, 10)) # 결과값 = A. 550
print("B.", sum_all(end=100)) # 결과값 = B. 5050
print("C.", sum_all(end=100, step=2)) #결과값 = C.2550

 

튜플

튜플은 리스트와 비슷한 자료형이다. 리스트와 다른 점은 한번 결정된 요소를 바꿀 수 없다는 것이다. 일반적으로 튜플은 함수와 함께 많이 사용하며 다음과 같은 형태로 생성한다.

(데이터, 데이터, 데이터, ...)

 

※ 괄호 없는 튜플

파이썬의 리스트와 튜플은 특이한 형태의 할당 구문으로 사용할 수 있다.

#리스트와 튜플의 특이한 사용
[a, b] = [10, 20]
(c, d) = (10, 20)
#출력
print("a: ", a) # 결과값 = a: 10
print("b: ", b) # 결과값 = b: 20
print("c: ", c) # 결과값 = c: 10
print("d: ", d) # 결과값 = d: 20

리스트와 튜플을 사용하면 이와 같은 형태로 변수를 선언하고 할당할 수 있다. 그런데 튜플은 정말 특이한 성질이 있다. 괄호를 생략해도 튜플로 인식할 수 있는 경우는 괄호를 생략해도 된다.

# 괄호가 없는 튜플
tuple_test = 10, 20, 30, 40 # 튜플을 입력한 것
print("# 괄호가 없는 튜플의 값과 자료형 출력")
print("tuple_test: ", tuple_test) # 결과값 = tuple_test: (10, 20, 30, 40)
print("type(tuple_test): ", type(tuple_test)) # 결과값 = type(tuple_test): <class> 'tuple'
print()

#괄호가 없는 튜플 활용
a, b, c = 10, 20, 30
print("#괄호가 없는 튜플을 활용한 할당")
print("a:", a) # 결과값 = a : 10
print("b: ", b) # 결과값 = b : 20
print("c: ", c) # 결과값 = c : 30

※ 변수의 값을 교환하는 튜플

a, b = 10, 20

print("# 교환 전 값")
print("a: ", a) # 결과값 = a: 10
print("b: ", b) # 결과값 = b: 20
print()
# 값을 교환
a, b = b, a

print("#교환 후 값")
print("a:", a) # 결과값 = a: 20
print("b:", b) # 결과값 = b: 10
print()

 

※ 튜플과 함수

튜플은 함수의 리턴에 많이 사용한다. 함수의 리턴에 튜플을 사용하면 여러 개의 값을 리턴하고 할당할 수 있기 때문이다.

# 함수를 선언
def test():
    return (10, 20)
# 여러 개의 값을 리턴받는다.
a, b = test()
# 출력
print("a: ", a) # 결과값 = a: 10
print("b: ", b) # 결과값 = b: 20

 

람다

요즘 프로그래밍 언어에서는 함수라는 '기능'을 매개변수로 전달하는 코드를 많이 사용한다. 그리고 이런 코드를 조금 더 효율적으로 작성할 수 있도록 파이썬은 람다(lambda)라는 기능을 제공한다.

 

※ 함수의 매개변수로 함수 전달하기

먼저 함수를 매개변수로 전달하는 것이 무엇인지 알아보고 람다까지 살펴보겠다.

다음은 함수의 매개변수로 함수를 전달하는 코드이다. 참고로 함수의 매개변수에 사용하는 함수를 콜백 함수(callback function)라고 한다.

# 매개변수로 받은 함수를 10번 호출하는 함수
def call_10_times(func):
    for i in range(10):
        func()
#간단한 출력하는 함수
def print_hello():
    print("안녕하세요")
# 조합하기
call_10_times(print_hello) # print_hello는 매개변수로 함수를 전달함.

 

※ filter() 함수와 map() 함수

함수를 매개변수로 사용하는 대표적인 표준 함수로 map() 함수와 filter() 함수가 있다.

 

map() 함수는 리스트의 요소를 함수에 넣고 리턴된 값으로 새로운 리스트를 구성해 주는 함수이다.

map(함수, 리스트)

filter() 함수는 리스트의 요소를 함수에 넣고 리턴된 값이 True인 것으로, 새로운 리스트를 구성해 주는 함수이다.

filter(함수, 리스트)
# 함수를 선언
def power(item):
    return item * item
def under_3(item):
    return item < 3
# 변수 선언
list_input_a = [1, 2, 3, 4, 5]
# map() 함수를 사용
output_a = map(power, list_input_a)
print("# map() 함수의 실행 결과")
print("map(power, list_input_a: )", output_a)
print("map(power, list_input_a: )", list(output_a))
print()
# filter() 함수를 사용
output_b = filter(under_3, list_input_a)
print("#filter() 함수의 실행 결과")
print("filter(under_3, list_input_a: )",output_b)
print("filter(under_3, list_input_a)", list(output_b))

※ 람다의 개념

매개변수로 함수를 전달하기 위해 함수 구문을 작성하는 것도 번거롭고, 코드 공간 낭비라는 생각이 들 수 있다. 많은 개발자들이 이러한 생각을 했고, 그래서 람다(lambda)라는 개념을 생각했다.

람다는 '간단한 함수를 쉽게 선언하는 방법'이다. 다음과 같은 형태로 만든다.

lambda 매개변수: 리턴값
728x90