불어버린 강물 덕분에 가는 길이 험난해졌다. 차도 많았고, 끼어들기도 많이 해야 했지만 결과적으로는 무사히 도착. 오늘은 프로그래밍의 꽃, 함수에 대해 배운다.
1. 함수 (Function)
함수란?
입력값을 받아서 어떠한 행동을 취하고 그 결과값을 반환(return)하는 코드
입력 값을 받아서 작업을 처리한 뒤, 그 결과 값을 반환하는 코드를 함수라고 한다. 하지만, 경우에 따라서 입력값이 없는 경우도 있고, 반환 값이 없는 경우도 있다. 함수가 무엇인지 알았으니 왜 사용하는지 생각해 보자. 함수를 사용하지 않는 방법도 있다. 하지만 함수를 사용하지 않는다면 코드의 길이는 걷잡을 수 없도록 길어질 것이다. 함수의 형태부터 살펴보자.
def 함수 이름( 매개 변수 ): # 매개 변수가 없을 수도 있다.
실행 코드
실행 코드
return 반환 값 # 반환 값이 없을 수도 있다.
정의하다인 'Define'의 앞부분을 따온 def와 자신이 원하는 함수 이름을 정한다. 소괄호 안에는 매개 변수를 입력할 수 있고, 입력하지 않을 수 있지만, 만약 입력하지 않는다고 해도 소괄호는 필히 붙여야 한다. 함수는 정의하는 부분과, 실행하는 부분으로 나뉜다. 위의 형태와 같이 함수를 정의한다고 해서 저 코드만으로 돌아가는 것이 아니다. 예시를 살펴보자.
def add(a, b):
return a + b
result = add(1, 2)
print(result)
# 해당 코드의 결과 값은 3이 반환될 것이다.
'def 함수명'을 통해 함수를 정의했고, 'result = add(매개변수)'를 통해 add함수를 호출한다. 이렇게 함수를 정의하는 것만으로는 사용이 불가능하다는 것을 알았으니 세부적인 내용을 살펴보자.
1-1. 매개 변수 (Parameter)와 전달 인자(Argument)
앞서 말했던 매개 변수는 호칭이 다양하다. 매개 변수의 영문명인 parameter 혹은 여러가지 이름으로 불리지만, 이 매개 변수는 지역 변수이다. 지역 변수란, 정해진 코드 내에서만 유효한 변수를 의미한다. 모든 변수는 유효 범위(Scope)가 있다.
전역 변수는 코드의 가장 바깥쪽에서 사용하는 변수이다. 그리고, 함수 혹은 반복문, 조건문에서 모두 사용 가능하다. 하지만 지역 변수를 보게 되면 정해진 코드 내에서만 사용이 가능하다. 전역 변수는 지역 변수의 역할을 할 수 있지만, 지역 변수는 전역 변수의 역할을 할 수 없다는 것을 알아두자. 전역 변수와 지역 변수에 대한 개념만 확실하다면 함수를 작성할 때 발생하는 오류를 많이 줄일 수 있다.
매개 변수를 알아보았으니 전달 인자에 대해 알아보자. 매개 변수는 함수를 정의할 때 전달 받은 값을 어떤 변수로 사용할지를 정하는 것이라면, 전달 인자는 함수를 호출할 때 어떤 값을 넘겨줄지 정하는 것이다.
def 함수명(매개변수):
실행 코드
함수명(전달 인자)
이와 같이 전달 인자가 곧 매개 변수가 된다. 이렇게 매개변수와 전달 인자를 살펴본 이유는 함수를 선언할 때 매개변수를 특정 방법으로 설정한다면 원하는 형태로 호출할 수 있기 때문이다. 그렇다면 그 종류를 살펴보자.
- Positional Argument: 인자를 정의된 매개변수의 순서대로 전달하는 방법
def func(arg1, arg2, /):
실행 코드
func(a, b) # 정상 동작
func(arg1 = a, arg2 = b) # 오류 발생
- Keword Argument: 매개변수를 지정하여 인자를 전달하는 방법
def func(*, arg1, arg2):
실행 코드
func(a, b) # 오류 발생
func(arg1 = a, arg2 = b) # 정상 동작
이렇게 함수를 선언할 때 매개 변수에 옵션을 추가한다면, 개발자의 의도대로 전달 인자를 설정할 수 있다.
1-2. 재귀함수
재귀 함수는 함수 내에서 같은 함수를 호출함으로써 반복문을 사용하지 않고, 반복적인 계산을 할 수 있게 해준다. 예시를 보자.
def factorial(x):
if x > 1:
return x * factorial(x - 1)
else:
return x
위의 코드는 팩토리얼을 구현한 코드로, 함수 내에서 팩토리얼 함수를 다시 호출하는 것을 볼 수 있다. 파이썬은 재귀함수를 추천하지 않기 때문에 재귀함수에 대한 제약이 있는 편이다. 대표적인 예로 Recursion Error가 있다. 이는 최대 재귀 횟수를 지정해 놓았고, 재귀 횟수가 최대 횟수를 넘어갈 시 생기는 오류이다. 다른 프로그래밍 언어에서는 반복문보다 재귀 함수를 사용하면 적은 비용을 필요로 한다. 재귀 함수의 원리는 다음과 같다.
fun1을 실행하다 함수 내부에서 자신과 같은 func1을 만나게 되면 다시 func1을 실행하게 된다. 이때 선행되고 있던 func1은 종료되지 않고 후행 func1의 동작이 끝날 때까지 대기한다. 최하단 func1 함수가 return을 하게 되면 차례대로 return 하는 방식으로 재귀함수가 종료된다.
2. Immutable 객체와 Mutable객체
저번 게시물에서 살펴봤듯이 파이썬에서는 Immutable 객체와 Mutable객체로 나뉜다. Immutable 객체는 수정 불가능한 객체이고, Mutable 객체는 수정 가능한 객체를 나타낸다. 이때 말하는 수정 가능, 불가능의 여부는 파이썬 코드 내에서 수정 여부를 말하는 것이 아니다. 바로 메모리에서 기존의 메모리를 수정할 수 있냐 없냐를 따지는 것이다. 말로 하면 이해하기 어려우니 그림과 함께 보자
Immutable 객체에는 대표적으로 숫자, 문자열, 튜플 등이 포함이 된다. 그림에 따르면 변수 a의 값을 변경하는 상황이다. 변수 a에는 정수가 예시로 들어갔지만, 숫자, 문자열, 튜플도 똑같은 방법을 사용한다. 숫자(정수, 실수), 문자열, 튜플 등의 수정 불가능 객체는 값이 변경되면 Call by Value 방식을 사용하여 새로운 메모리를 할당하여 변경된 값을 메모리에 저장하게 된다.
반대로 Mutable 객체인 dictionary, list 등의 객체들은 call by reference 방식을 사용하게 된다.
Mutable 객체의 경우 Call by Reference 방식을 사용하여 정해진 메모리 내에서 수정을 진행하게 된다. 이 차이로 인해 Mutable 객체와 Immutable 객체의 차이가 발생하게 된 것이다. 하지만 여기서 재미있는 점을 발견할 수 있다. 과연 Mutable 객체의 말단에서는 어떤 일이 일어날까?
그림을 보면 할당된 메모리에 list가 저장된다. 겉으로 보기에는 list는 메모리 한 곳에 저장되어 있는 것처럼 보이지만, 그 내면을 보면 각각의 요소로 메모리가 나뉘게 된다. 나뉜 메모리에 할당된 요소들은 또 다른 메모리를 가리키게 된다. 그림을 기준으로 가장 하위에서 값의 수정이 일어나면 이 행동은 Immutable 하다고 할 수 있지만, 최상위 메모리에서는 원래 가리켰던 메모리가 바뀌는 것이 아니기 때문에 Mutable 할 수 있다. 모순적이지만 신기하고 재미있다.
Mutable 객체와 Immutable 객체 모두 파이썬 코드 내에서는 수정이 가능하지만, 실제 메모리 상에서는 수정이 불가능한 경우가 있다. 지금까지는 몰랐던 지식이지만, 전공 수업을 듣고 다시 공부하게 되니 이해가 되는 부분들이었다.
고등학교 시절부터 파이썬을 공부해왔지만, 그때 공부했던 내용과
지금 공부하는 내용의 수준 차이가 확연하게 느껴졌다.
전공 지식을 이용하여 이번 부트캠프 수업에서 많은 지식들을 배우고 싶다.
'ABC부트캠프 데이터 탐험가 과정' 카테고리의 다른 글
[7일차] ABC 부트캠프 파이썬 데이터분석 및 Pandas 모듈 (2) | 2024.07.13 |
---|---|
[6일차] ABC 부트캠프 파이썬 표준 라이브러리, 객체 지향, 파일 경로 (0) | 2024.07.11 |
[4일차] ABC 부트캠프 파이썬 기초지식 2 (0) | 2024.07.09 |
[3일차] ABC 부트캠프 파이썬 환경구축 및 기초지식 다지기 (0) | 2024.07.08 |
[2일차] ABC 부트캠프 ESG 포럼 & 세미나 (0) | 2024.07.06 |