함수라는 것은 우리에게 비교적 익숙하게 다가온다. 수학 시간만 해도 함수랑 살았던 기억이 있다. 하지만 그 때는 대부분 그래프에 대해서만 생각을 했을 것이다. 지금은 어떤 입력값을 가지고 일을 수행한 후에 결괏값을 출력하는 그 자체에 대해 중점적으로 해석해야 한다. 그렇다면 함수가 왜 난데없이 프로그래밍에서 등장하는 것이고 사용함으로써 얻는 장점은 무엇일까? 우리가 앞으로 프로그래밍을 할 때 의미없이 그냥 반복해서 사용해야 할 내용들이 있을 때 함수를 필요로 한다. 반복되는 기능같은 것들을 한 곳에 묶어서 "함수"를 만들어 놓기만 하면 그런 기능들을 필요로 할 때 단지 "함수"를 불러서 사용만 하면 된다는 것이다. 그리고 보기에도 깔끔해보인다. 다만, 파이썬에서의 함수는 수학에서의 함수와는 다르게 입력값과 출력값이 없어도 된다.
그럼 파이썬에서 함수는 어떻게 만드냐? 간단하다. def 함수 이름(매개 변수) : 밑에 수행할 문장들을 쓰면 끝이다. def는 함수를 만들 때 사용하는 예약어이고 함수 이름은 내 맘대로 쓰면 된다. 괄호 안에 있는 변수는 이 함수가 나중에 전달받을 입력값을 넣을 박스라고 생각하면 된다.

위의 코드처럼 두 개의 수를 더하는 함수 이름은 add이고 ①의 x, y는 "매개 변수" 이고 함수를 호출하는 ②의 7, 8은 "인수" 이다. ②에서처럼 함수를 불러서 사용할 때 서로 더할 두 개의 입력값 7, 8이 add 함수에서 입력값을 넣을 박스 x, 박스 y에 전달되면 두 수를 더한 x + y (= 7 + 8)가 출력(return)된다.
대부분의 함수가 이런 식으로 사용되지만 앞서 언급했듯이 프로그래밍에서의 함수는 입력값과 출력값이 없어도 된다고 했다. 그렇다면 먼저 입력값이 없는 함수를 알아보자. 이는 입력값에 상관없이 어떤 특정한 출력값만 출력하고 싶을 때 만들면 된다. 함수를 사용할 때는 입력값이 없으므로 함수 이름()과 같이 괄호 안에 아무것도 넣지 않고 사용하면 된다. 출력값이 없는 함수는 원래 함수를 사용하던 것처럼 사용하면 된다.
이번엔 입력값이 얼마나 될지 모르는 상황이면 어떻게 대처할 것인가에 대해 알아보겠다. 만약 입력받은 인수들을 모두 더하는 add 함수가 있다고 해보자. 그리고 인수가 1, 2, 3, 4, 5, 6, 7, 8, 9, 10이라고 해보면, 함수 add(a, b, c, d, e, d, f .....)처럼 인수의 개수만큼 다 맞춰서 매개 변수를 다 쓰기에는 귀찮지 않은가? 바로 이때 add(*args)처럼 매개 변수 이름 앞에 * 을 붙여주면 입력값들을 전부 모아 튜플로 만들어 준다.

" *args 는 인수 값으로 몇 개를 넣든 상관없이 알아서 해줄게" 라는 의미이므로 *(내가 원하는 이름)으로 설정해도 무방하긴 하지만, 관례상 arguments가 인수를 뜻하므로 *args 로 써준다. 또한, 아래의 코드와 같이 함수의 매개 변수를 입력하는 괄호 안에 *args 외의 매개 변수를 추가할 수도 있다.

매개 변수 앞에 별 2개(**)를 붙이는 "키워드 매개 변수 **kwargs" 이라는 것도 있다. 매개 변수 앞에 별 2개를 붙이면 그 매개 변수는 "딕셔너리" 가 되고 그에 대한 입력값들이 모두 그 딕셔너리에 저장된다. 아래의 코드처럼 말이다.

그리고 함수에서 중요한 사항은 리턴(return)값은 언제나 "하나" 라는 점이다. 그렇다면 아래의 코드를 보고 이야기해보자.

보다시피 return 값이 굉장히 많아 보이는데 오류는 나지 않고 어찌저찌 (72, 2.0)이라고 출력이 되었다. 바로 return 값 a * b, a / b는 "하나"의 튜플값이기 때문이다. 또한, 바로 밑에 return 값 a % b가 출력되지 않은 것을 확인할 수 있다. 이는 함수가 return 문을 만나면 그 리턴값을 돌려 준 후 함수의 기능을 마치는 것이다. 따라서 즉시 함수를 빠져나가야 하는 특수한 상황이라면 return 을 입력하면 된다. 리턴값이 없는 함수에서 return으로 함수를 빠져나가는 방법은 프로그래밍에서 자주 사용되므로 잘 숙지해두자.
다음은 다른 형태로 함수에게 인수를 전달하는 방법에 대해 알아보자. 바로 매개 변수에 초깃값을 설정해주는 것이다. 예시 코드를 살펴보면서 이야기해보자.

보다시피 1번 줄에 fresh = True처럼 fresh라는 매개 변수에 True라는 초깃값을 설정해준 것을 볼 수 있다. 기본적으로 fresh가 True이므로 10번 줄처럼 굳이 인수에 True를 주지 않아도 "신선합니다." 라는 문장 출력이 가능하다. 하지만 인수에 False를 준다면 fresh가 참이라는 if 조건문에 부합하지 않으므로 print("썩었습니다.")가 실행된다. 또한 매개 변수의 초깃값을 설정할 때 매개 변수의 위치도 꽤 중요하다. 가령, fruit_state(fruit, fresh=True, sugar) : 라고 했을 때 똑같이 fruit_state("사과", 10)을 실행한다면 인수 10이 fresh 매개 변수와 sugar 매개 변수 중에 어떤 곳에 들어가야 할지 파이썬은 알 방법이 없다. 따라서 초깃값을 설정하고 싶은 매개 변수가 있다면 맨 뒤쪽에 놓도록 하자.
학교 강의 시간이나 프로그래밍을 할 때, "이 변수는 함수 안에서 선언해야지", "이건 전역 변수로 써야 되니까 바깥으로 빼야지." 라는 말들을 한 번쯤은 들어봤을 것이다. 필자도 분명히 변수 선언해서 값을 집어넣었는데 원하는 값이 안 나와서 당혹스러웠던 경험들이 있다. 책(p.167)의 예제를 살펴보자.

이걸 보고 "왜 1이 출력되지?" 생각한 사람, 분명히 있을 거다. 위에서 a = 1 이라고 했고 test1 함수에서 a에 1 더하니까 그거 print 하면 2 아니여? 결론부터 말하면, 1번 줄에 있는 a랑 함수 안에 있는 a랑은 그냥 남남이다. 함수 안에서 사용된 저 매개 변수 a는 함수 안에서만 사용되는 "지역 변수" 이다. 명심하자, 함수 안에서랑 밖에서의 변수는 구분지어야 한다.
여기서 넘어가면 찝찝하니 test1 함수에서 a를 2로 하나 증가시키려면 어떻게 해야하는지도 알려줘야 인지상정. 방법은 두 가지다. 첫 번째, return 사용하기. 두 번째, global 명령어 사용하기.

먼저 함수 안에서 a에 1을 증가시킨 값을 리턴시킨 후, 그 리턴값을 a에 다시 할당시키면 된다. 여기에서도 여전히 6번 줄의 a = test1(a) 왼쪽 a와 오른쪽 괄호 안에 들어 있는 a는 다른 것이다. 두 번째 방법 global은 함수 밖에 있는 변수를 함수 안에서 직접 사용할 수 있게 하는 명령어인데 그리 권장하지는 않는다. 왜냐하면 함수는 외부 변수에 종속되지 않고 독립적으로 존재하는 것이 훨씬 좋기 때문이다. 그냥 이런 방법도 있구나 정도로만 보고 넘어가자.
마지막으로 lambda 예약어라는 것도 있는데 def 와 똑같다. 7과 8을 더하는 코드를 위에서 def 를 썼던 방식과 비교하면서 한 번 보고 넘어가도록 하자.

파이썬 프로그래밍에 관한 글은 "이지스퍼블리싱"의 "Do it!, 점프 투 파이썬"이라는 책을 학습하고 정리한 것입니다.
'Programming Language > Python' 카테고리의 다른 글
파이썬 - (★클래스★) (0) | 2023.07.13 |
---|---|
파이썬 - (사용자 입출력 ~ 파일 읽고 쓰기) (0) | 2023.07.11 |
파이썬 - (반복문 中 for 문) (0) | 2023.07.10 |
파이썬 - (반복문 中 while 문) (0) | 2023.07.09 |
파이썬 - (if 제어문) (0) | 2023.07.08 |