함수 (function)
- 이번 글에서는 파이썬에서 많이 쓰이는 함수의 정의부터 다양한 활용법에 대해 다루고자 함
1. 함수의 정의, 함수의 호출
- 프로그래밍을 진행하다보면 동일한 코드를 몇 번이고 동일하게 처리해줘야하는 경우가 있음
- 함수란 인수(변수)를 입력 받아 코드를 실행하고 결과물을 출력하도록 하는 입력값과 출력값의 관계를 의미함
- 쉽게 말해 입력값을 받고 출력값을 계산하는 기계 혹은 틀
- 파이썬에서는
def
라는 구문을 통해서 함수를 정의할 수 있으며, 함수를 작성하는 행위를 함수를 정의한다
라고 표현함
- 이렇게 정의된 함수는 함수명을 통해 기능을 수행하도록 불러올 수 있고, 이러한 행위는
함수를 호출한다
라고 표현함
def 함수명(인수 목록):
실행구문
...
return 반환값
함수명(인수 목록)
def hello(var):
print('Hello', var)
hello('python')
'''
Hello python
'''
def sum_num(num1, num2):
print(f"num1 : {num1}, num2 : {num2}")
return num1 + num2
sum_num_12 = sum_num(3,6)
print(f"sum : {sum_num_12}")
'''
num1 : 3, num2 : 6
sum : 9
'''
- 함수의 정의를 함수의 호출보다 먼저 시행해야하는 것이 원칙이긴하지만, 실제로는 동일한 코드 파일 안에서는 호출을 먼저하고 정의를 뒤에 해주어도 동작 오류가 발생하지는 않긴함
- 이는 객체지향프로그래밍(OOP)의 특징을 가지기 때문이라 설명할 수 있는데, 이에 대한 내용은 뒤에 다시 설명할 예정)
- 함수를 한번 정의하면 해당 함수는 몇번이고 호출하여 재사용할 수 있기 때문에 반복적으로 작업을 수행하는 경우 훨씬 효율적인 프로그래밍이 가능해짐
2. 함수의 인수(argument)
- 함수에게 전달하는 정보를 인수(argument)라하며, 이는 매개변수(parameter)라고도 불림
- 함수를 정의할때, 함수명 뒤에 소괄호
()
에 인수를 담아서 함수에 전달하게 됨
- 소괄호에 묶어서 전달한다는 것은
튜플
의 형태로 값을 전달한다는 것과 같은 의미이기 때문에, 함수를 정의할 때의 인수의 순서
와 함수를 호출할 때의 인수의 순서
가 일치해야함을 의미함
- 순서가 중요한 것은 인수의 변수명을 지정하지 않고 값만을 넣어서 호출하는 경우에 해당하는 것이고, 호출시 변수명을 직접 적어주는 경우엔 순서를 맞춰서 넣어줄 필요는 없음
- 다만 일부의 변수만을 따로 지정하는 경우엔, 앞 쪽 변수는 순서를 반드시 맞춰줘야하고, 나머지 변수들은 기본값이 지정되지 않은 경우 반드시 값을 정의해 주어야 함
- 모든 함수가 인수를 반드시 가져야 할 필요는 없어서, 인수를 따로 정의하지 않고도 함수를 정의하고 호출할 수 있음
- 이때는 호출할 때 어떠한 인수도 넣지 않아야 오류가 발생하지 않음
def sums(num1, num2, num3):
sum_num = num1 + num2 + num3
return sum_num
sum_1 = sums(3, 6, 9)
print(sum_1)
'''
18
'''
sum_2 = sums(3, num3=9, num2=6)
print(sum_2)
'''
18
'''
def sums(num1, num2, num3=10):
sum_num = num1 + num2 + num3
return sum_num
sum_1 = sums(1, 2)
print(sum_1)
'''
13
'''
sum_2 = sums(1, 2, 5)
print(sum_2)
'''
8
'''
sum_3 = sums(1, num2=3)
print(sum_3)
'''
14
'''
- Python에서는 함수를 정의할 때 인수 앞에
*
를 붙임으로써 콤마,
로 구분한 인수를 한번에 여러개 전달할 수 있으며, 이때 전달된 변수는 함수 내부에서 튜플로 저장됨
- 이러한 경우 일반적으로는
*args
라는 이름으로 설정함
def func(*args):
print(args)
func(1,2,3,4,5)
'''
(1, 2, 3, 4, 5)
'''
- 함수를 정의할 때 인수 앞에
**
를 붙이면 키워드로 구분된 인수들을 한번에 여러개 전달할 수 있으며, 이때 전달된 변수는 함수 내부에서 딕셔너리 형태로 저장됨
- 이러한 경우 일반적으로는
**kwargs
아는 이름으로 설정함
def func(**kwargs):
print(kwargs)
func( a=1, b=2, c=3, d=4)
'''
{'a':1, 'b':2, 'c':3, 'd':4}
'''
*args
나 **kwargs
처럼 인수의 개수를 정하지 않고 정의하는 경우, 이러한 인수를 가변길이인수
(variadic argument)라 부름
3. 전역변수와 지역변수
- 파이썬에서 변수는 크게 전역변수(global), 지역변수(local) 두 종류로 구분할 수 있고, 전역변수와 지역변수는 정의되는 위치와 적용되는 범위에 있어 차이가 있음
지역변수 (local variables)
: 함수 내부에서 정의되어 함수 내부에서만 쓰일 수 있는 변수
- 함수가 종료되면 메모리에 더이상 저장되지 않고 제거됨
전역변수 (global variables)
: 하나의 파이썬 파일에 있는 모든 함수나 코드에 쓰일 수 있는 변수
- 함수 외부에서 정의된 변수는 global 변수로써 함수 내부에서도 쓰일 수 있음
- 함수 내부에서
global
구문으로 정의된 변수는 함수 안에서 정의되었지만 전역변수로 저장되어 동일한 파이썬 파일내에 모든 함수나 코드에서 쓰일 수 있음
- 이때 각 변수명이 이용될 수 있는 통용 범위를
스코프(scope)
라고 부름
g_var = '전역변수'
def variables():
local_var = '지역변수'
global global_var
global_var = '함수 내부 전역변수'
print('--함수 내부 변수들--')
print('외부 전역변수 g_var : ', g_var)
print('내부 전역변수 global_var : ', global_var)
print('함수 지역변수 local_var : ', local_var)
variables()
print('\n--함수 외부 변수들--')
print('외부 전역변수 g_var : ', g_var)
print('내부 전역변수 global_var : ', global_var)
print('함수 지역변수 local_var : ', local_var)
'''
--함수 내부 변수들--
외부 전역변수 g_var : 함수 외부 전역변수
내부 전역변수 global_var : 함수 내부 전역변수
함수 지역변수 local_var : 지역변수
--함수 외부 변수들--
외부 전역변수 g_var : 함수 외부 전역변수
내부 전역변수 global_var : 함수 내부 전역변수
NameError: name 'local_var' is not defined
'''
- 이처럼 지역변수는 함수 내부에서만 저장되고 이용되며, 함수 내부에서는 global 구문을 통해서 함수 내부에서 정의된 변수를 전역변수로써 저장하여 이용할 수 있음
- 이러한 전역변수와 지역변수가 정의되는 위치와 적용되는 범위를 고려하여 코드를 작성하는 것이 중요함
4. lambda 연산자
- 간단한 함수를 정의하는 경우에는 lambda 연산자(lambda operator)를 통해 보다 효율적이고 간결한 코드를 작성할수 있음.
- lambda 함수명을 지정하지 않고도 함수를 정의하고 적용할 수 있음
- 이러한 특성 때문에 람다함수는
무명함수
혹은 익명함수
라고도 불림 (anonymous fuction)
lambda 인수: 식
multi_words = lambda word1, num : word1 * num
result = multi_words('word!\t', 5)
print(result)
'''
word! word! word! word! word!
'''
map()
함수를 활용하여 이터레이터(iterator) 요소별로 함수를 적용할 수 있음
- map(함수, 이터레이터)
- map 함수는 이터레이터(iterator)를 반환함 (for문에 쓰이기 적합!)
data = [1,2,3,4,5]
for d in data:
print(d*2)
'''
2
4
6
8
10
'''
for d in [x*2 for x in data]:
print(d)
'''
2
4
6
8
10
'''
for d in map(lambda x: x*2, data):
print(d)
'''
2
4
6
8
10
'''
str_list = ['test1', 'test2', 'test4test5', 'test3']
shout_str = map(lambda item : item + '!!!', str_list)
shout_list = list(shout_str)
print(shout_list)
'''
['test1!!!', 'test2!!!', 'test4test5!!!', 'test3!!!']
'''
filter()
함수를 활용하여 이터레이터 요소를 조건에 맞게 걸러낼 수 있음
- filter(함수, 이터레이터)
- filter 함수는 이터레이터(iterator)를 반환함 (for문에 쓰이기 적합!)
data = [1,2,3,4,5,6,7,8,9]
for d in data:
if d % 2 == 1:
continue
else:
print(d)
'''
2
4
6
8
'''
for d in [x for x in data if x % 2 == 0]:
print(d)
'''
2
4
6
8
'''
for d in filter(lambda x : x % 2 == 0, data):
print(d)
'''
2
4
6
8
'''
users = ['frodo', 'samwise', 'merry', 'pippin', 'aragorn', 'boromir', 'legolas', 'gimli', 'gandalf']
result = filter(lambda u : len(u) >= 6, users)
result_list = list(result)
print(result_list)
'''
['samwise', 'pippin', 'aragorn', 'boromir', 'legolas', 'gandalf']
'''
5. 데코레이터
- 이번에는 복잡한 함수의 경우에 적용되는 데코레이터를 다루어봄
- 함수를 인자로 받아서 기능을 추가한 뒤에 다시 함수를 반환하는 경우엔 코드가 다소 복잡해질 수 있고, 매번 설정하기에 복잡한 경우가 있음
- 이러한 문제를 데코레이터 함수를 통해 해결할 수 있음
- 데코레이터 함수를 정의하고, 데코레이터 함수를 적용할 함수의 윗줄에
@
를 붙여줌으로써 데코레이터 기능을 사용할 수 있음
def deco( func ):
def wrapper( var ) :
추가 기능
return 반환변수
return wrapper
@deco
def 기능을 추가하려는 함수:
...
- 데코레이터 사용 예시 (문자열을 변환하여 출력하기)
def deco(func):
def wrapper(x):
xx = '---' + x + '---'
return func(xx)
return wrapper
@deco
def print_msg(msg):
print(f"{msg}를 입력했습니다.")
message = "Hello!"
print_msg(message)
'''
---Hello!---를 입력했습니다.
'''
- 데코레이터 사용 예시 (함수 실행 소요시간 측정하기)
import time
from functools import wraps
def check_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print("@check_time of '{0:s}' took {1:e} seconds"
.format(func.__name__, end_time - start_time))
return result
return wrapper
@check_time
def sum_num_for(n):
s = 0
for i in range(1, n+1):
s += i
return s
sum_num_for(100000)
'''
@check_time of 'sum_num_for' took 4.498243e-03 seconds
5000050000
'''
@check_time
def sum_num(n):
return n * (n + 1) / 2
sum_num(100000)
'''
@check_time of 'sum_num' took 0.000000e+00 seconds
5000050000.0
'''
6. 제너레이터
- 파이썬에서는 반복문을 통해 얻은 요소를 이터레이터(iterator)로 반환하는 함수를 정의할 수 있는데, 이러한 함수를 제너레이터(generator)라고함
- 함수 내부에서
yield문
을 통해 각 요소를 반환하도록 정의할수 있고, 이 때는 return문을 사용하지 않아야 함
- 무한 루프에 빠지는 경우에도 이터레이터(iterator)를 생성할 수 있지만, 이를 for문으로 이용하면 무한루프에 빠지게 되므로.. 이부분은 조심해서 사용할 필요가 있음
- 이터레이터(iterator)에
next(이터레이터)
함수를 이용하면, 요소를 하나씩 살펴 볼 수 있음
def make_iter(x):
while True:
yield x
x += 1
iterator = make_iter(0)
print(iterator)
'''
<generator object make_iter at 0x000002A9ACB39DC8>
'''
print(next(iterator))
print(next(iterator))
print(next(iterator))
'''
0
1
2
'''
def make_iter(min_x, max_x):
x = min_x
while True:
yield x
if x < max_x:
x += 1
else:
break
iterator = make_iter(0, 10)
print(iterator)
'''
<generator object make_iter at 0x000002A9AE8E6148>
'''
for i in iterator:
print(i)
'''
0
1
2
3
4
5
6
7
8
9
10
'''
마무리
- 이번 글에서는 Python에서 함수를 작성하는 방법과 다양한 활용법에대해 다루었음
- 함수를 정의하는 방법, 함수를 호출하는 방법
- 함수에 전달할 인수(args)를 설정하는 방법
- 지역변수와 전역변수의 개념
- lambda 연산자의 기본적인 사용법
- 데코레이터와 제너레이터의 기본적인 사용법
- 이외에도 추가적으로 정리할 내용이 생기면 업데이트할 예정!
- 다음 글에서는 OOP(객체지향프로그래밍)과 Class에서 대해 다루어 보고자 함
- 화이팅!