함수(Function)는 입력값을 받아 특정 작업을 수행하고 결과를 반환하는 코드의 묶음이다.
반복되는 코드를 함수로 만들어 두면 코드의 재사용성과 가독성을 높일 수 있다.
*args함수는 쉽게 생각하면 어떤 값을 넣으면 정해진 작업을 수행하는 하나의 기능이다.
예를 들어 믹서를 생각해 보면 이해하기 쉽다.
과일 → 믹서 → 주스
함수에서는 다음과 같이 생각할 수 있다.
입력값 → 함수 → 반환값
예를 들어 두 숫자를 더하는 함수라면
def add(a, b):
return a + b
다음과 같이 사용할 수 있다.
result = add(3, 4)
print(result)
실행 결과
7
즉,
3, 4 → add 함수 → 7
이라고 볼 수 있다.
프로그램을 작성하다 보면 동일한 코드를 여러 번 작성해야 하는 경우가 생긴다.
예를 들어
a = 10
b = 20
print(a + b)
이러한 계산을 프로그램 곳곳에서 반복한다면 코드가 길어지고 관리하기 어려워진다.
이럴 때 함수를 만들어 사용할 수 있다.
def add(a, b):
return a + b
이후에는
add(10, 20)
add(30, 40)
add(50, 60)
처럼 필요한 곳에서 다시 사용할 수 있다.
파이썬에서는 def를 사용하여 함수를 만든다.
기본 구조는 다음과 같다.
def 함수이름(매개변수):
수행할 문장
return 반환값
예를 들어
def add(a, b):
return a + b
각 부분을 살펴보면
def add(a, b):
return a + b
| 구성 | 설명 |
|---|---|
def | 함수를 정의하는 예약어 |
add | 함수 이름 |
a, b | 매개변수 |
return | 함수의 결과를 반환 |
a + b | 반환할 값 |
함수를 정의했다고 바로 실행되는 것은 아니다.
def add(a, b):
return a + b
함수를 실제로 실행하려면 호출해야 한다.
result = add(3, 4)
print(result)
결과
7
함수를 공부할 때 자주 헷갈리는 용어가 있다.
바로 매개변수(Parameter) 와 인수(Argument) 이다.
def add(a, b):
return a + b
add(3, 4)
여기서
a, b
는 매개변수이다.
반면
3, 4
는 인수이다.
정리하면
| 용어 | 의미 | 예시 |
|---|---|---|
| 매개변수(Parameter) | 함수에서 값을 전달받는 변수 | a, b |
| 인수(Argument) | 함수를 호출할 때 실제로 전달하는 값 | 3, 4 |
def add(a, b): # a, b → 매개변수
return a + b
add(3, 4) # 3, 4 → 인수
⭐ 매개변수는 함수를 정의할 때, 인수는 함수를 호출할 때 사용한다고 기억하면 편하다.
함수는 입력값과 반환값이 존재하는지에 따라 크게 4가지 형태로 나눌 수 있다.
| 구분 | 입력값 | 반환값 |
|---|---|---|
| 일반적인 함수 | O | O |
| 입력값이 없는 함수 | X | O |
| 반환값이 없는 함수 | O | X |
| 입력값과 반환값이 없는 함수 | X | X |
가장 일반적인 함수 형태이다.
def add(a, b):
result = a + b
return result
사용
result = add(3, 4)
print(result)
결과
7
구조는 다음과 같다.
입력값 → 함수 → 반환값
3, 4 add 7
입력값이 없어도 함수는 만들 수 있다.
def say():
return "Hi"
호출할 때 괄호 안에 아무것도 전달하지 않는다.
result = say()
print(result)
결과
Hi
다음 함수는 입력값은 있지만 return이 없다.
def add(a, b):
print(a + b)
호출하면
add(3, 4)
결과
7
화면에는 7이 출력되지만 반환값은 없다.
이 부분은 특히 주의해야 한다.
result = add(3, 4)
print(result)
결과
7
None
왜냐하면
print()
은 단순히 화면에 값을 출력하는 것이고,
return
은 함수의 값을 반환하는 것이기 때문이다.
⭐
return은 완전히 다르다.
입력값도 없고 반환값도 없는 함수이다.
def say():
print("Hi")
사용 방법은 단순하다.
say()
결과
Hi
함수를 호출할 때 어떤 매개변수에 어떤 값을 전달할 것인지 직접 지정할 수도 있다.
def sub(a, b):
return a - b
일반적으로는
sub(7, 3)
처럼 호출한다.
하지만 다음처럼 사용할 수도 있다.
sub(a=7, b=3)
결과
4
매개변수를 직접 지정하면 순서를 바꿔도 된다.
sub(b=5, a=3)
실제로는
a = 3
b = 5
이므로 결과는
-2
가 된다.
*args함수를 만들 때 입력값이 몇 개 들어올지 모르는 경우가 있다.
예를 들어
add(1, 2)
add(1, 2, 3)
add(1, 2, 3, 4, 5)
처럼 입력값의 개수가 계속 달라질 수 있다.
이럴 때 *args를 사용한다.
def 함수이름(*args):
수행할 문장
예제
def add_many(*args):
result = 0
for i in args:
result += i
return result
사용
print(add_many(1, 2, 3))
결과
6
다음처럼 더 많은 값을 넣어도 된다.
print(add_many(1, 2, 3, 4, 5))
결과
15
*args는 튜플이다중요한 특징이 하나 있다.
def test(*args):
print(args)
test(1, 2, 3)
결과
(1, 2, 3)
즉,
*args
로 전달된 값들은 함수 내부에서 튜플 형태로 저장된다.
test(1, 2, 3)
↓
args = (1, 2, 3)
⭐
*args= 여러 개의 위치 인수를 튜플로 묶어서 받는다.
def calc(choice, *args):
if choice == "add":
result = 0
for i in args:
result += i
elif choice == "mul":
result = 1
for i in args:
result *= i
return result
사용
print(calc("add", 1, 2, 3, 4, 5))
결과
15
print(calc("mul", 1, 2, 3, 4, 5))
결과
120
여기서
choice
에는 "add" 또는 "mul"이 들어가고
args
에는 나머지 숫자가 튜플 형태로 저장된다.
**kwargs*args가 여러 개의 값을 튜플로 받는다면
**kwargs
는 여러 개의 키워드 인수를 받을 때 사용한다.
def print_info(**kwargs):
print(kwargs)
호출
print_info(name="pingu", age=25)
결과
{'name': 'pingu', 'age': 25}
즉,
name="pingu"
age=25
가
{
"name": "pingu",
"age": 25
}
와 같은 딕셔너리 형태로 저장된다.
⭐
**kwargs= 여러 개의 키워드 인수를 딕셔너리로 묶어서 받는다.
*args와 **kwargs 비교| 구분 | 저장 형태 | 사용 형태 |
|---|---|---|
*args | 튜플 | func(1, 2, 3) |
**kwargs | 딕셔너리 | func(name="pingu", age=25) |
간단하게 기억하면
*args
↓
(1, 2, 3)
튜플
**kwargs
↓
{"name": "pingu", "age": 25}
딕셔너리
다음과 같이 작성할 수 있다.
def add_and_mul(a, b):
return a + b, a * b
사용
result = add_and_mul(3, 4)
print(result)
결과
(7, 12)
값이 2개 반환되는 것처럼 보이지만 실제로는
(7, 12)
라는 하나의 튜플이 반환된 것이다.
따라서 다음처럼 각각의 변수로 받을 수도 있다.
add_result, mul_result = add_and_mul(3, 4)
결과적으로
add_result = 7
mul_result = 12
가 된다.
def test(a, b):
return a + b
return a * b
두 번째 return은 실행되지 않는다.
왜냐하면 함수는
return
을 만나는 순간 즉시 종료되기 때문이다.
즉,
return a + b
가 실행되면 함수는 끝난다.
return은 값을 반환하지 않고 함수만 종료하는 용도로 사용할 수도 있다.
def check_name(name):
if name == "admin":
return
print(name)
check_name("pingu")
결과
pingu
하지만
check_name("admin")
은 return을 만나 함수가 종료되므로 아무것도 출력하지 않는다.
함수를 만들 때 매개변수에 기본값을 지정할 수도 있다.
def introduce(name, age, job="student"):
print(name)
print(age)
print(job)
다음처럼 호출하면
introduce("pingu", 25)
job에는 자동으로
"student"
가 들어간다.
하지만 직접 값을 전달하면 기본값을 덮어쓴다.
introduce("pingu", 25, "developer")
다음은 가능하다.
def test(a, b, c=10):
pass
하지만 다음은 오류가 발생한다.
def test(a, b=10, c):
pass
왜냐하면 파이썬 입장에서는 호출할 때 전달된 값이 어느 매개변수에 들어가야 하는지 명확하지 않기 때문이다.
따라서
⭐ 기본값이 있는 매개변수는 기본값이 없는 매개변수보다 뒤에 작성해야 한다.
def test(a, b, c=10):
처럼 작성해야 한다.
다음 코드를 살펴보자.
a = 1
def vartest(a):
a = a + 1
vartest(a)
print(a)
결과는
1
이다.
처음 보면 2가 나올 것 같지만 그렇지 않다.
함수 안의
a
와 함수 밖의
a
는 서로 다른 변수이기 때문이다.
함수 밖 a = 1
↓ 함수 호출
함수 안 a = 1
함수 안 a = 2
↓ 함수 종료
함수 밖 a = 1
함수 내부의 변수는 기본적으로 함수 내부에서만 사용할 수 있다.
이를 지역 변수(Local Variable) 라고 한다.
함수 밖의 변수 값을 변경하는 대표적인 방법은 두 가지가 있다.
a = 1
def vartest(a):
a = a + 1
return a
a = vartest(a)
print(a)
결과
2
함수에서 새로운 값을 반환하고
a = vartest(a)
를 통해 다시 변수 a에 저장한 것이다.
일반적으로 이 방법을 사용하는 것이 좋다.
a = 1
def vartest():
global a
a = a + 1
vartest()
print(a)
결과
2
global a는
함수 밖에 있는 전역 변수
a를 함수 안에서도 직접 사용하겠다.
라는 의미이다.
하지만 함수가 외부 변수에 의존하게 되므로 특별한 이유가 없다면 지나친 global 사용은 피하는 것이 좋다.
리스트와 딕셔너리는 변경 가능한 자료형(Mutable) 이다.
따라서 함수 안에서 값을 변경하면 원본도 변경될 수 있다.
def add_number(numbers):
numbers.append(4)
a = [1, 2, 3]
add_number(a)
print(a)
결과
[1, 2, 3, 4]
함수 내부에서 리스트를 수정했지만 함수 밖의 리스트 a까지 변경되었다.
⭐ 리스트와 딕셔너리를 함수에 전달할 때는 원본 데이터가 변경될 수 있다는 점을 기억하자.
lambda는 함수를 간단하게 한 줄로 만들 때 사용한다.
일반적인 함수
def add(a, b):
return a + b
를 lambda를 사용하면 다음과 같이 작성할 수 있다.
add = lambda a, b: a + b
사용
print(add(3, 4))
결과
7
기본 구조는
함수이름 = lambda 매개변수: 표현식
이다.
예를 들어
square = lambda x: x ** 2
print(square(5))
결과
25
lambda는 return을 직접 작성하지 않아도 표현식의 결과를 자동으로 반환한다.
def square(x):
return x ** 2
square = lambda x: x ** 2
두 함수는 같은 역할을 한다.
독스트링(Docstring)은 함수가 어떤 기능을 하는지 설명하기 위한 문자열이다.
함수 바로 아래에 """ """를 사용하여 작성한다.
def add(a, b):
"""
두 숫자를 더한 값을 반환하는 함수
a: 첫 번째 숫자
b: 두 번째 숫자
"""
return a + b
작성된 독스트링은 다음과 같이 확인할 수 있다.
print(add.__doc__)
독스트링을 작성하면
등을 쉽게 확인할 수 있어 코드를 관리하기 좋아진다.
| 문법 | 의미 |
|---|---|
def | 함수 정의 |
return | 값 반환 및 함수 종료 |
| Parameter | 함수를 정의할 때 사용하는 변수 |
| Argument | 함수를 호출할 때 전달하는 실제 값 |
*args | 여러 개의 위치 인수를 튜플로 받음 |
**kwargs | 여러 개의 키워드 인수를 딕셔너리로 받음 |
| 기본값 매개변수 | 값이 전달되지 않았을 때 사용할 기본값 |
| 지역 변수 | 함수 내부에서만 사용하는 변수 |
global | 함수 밖의 전역 변수 사용 |
lambda | 간단한 함수를 한 줄로 작성 |
| Docstring | 함수에 대한 설명 작성 |
print와 return 차이함수에서 특히 중요한 부분이다.
def test1():
print(10)
def test2():
return 10
두 함수는 전혀 다르다.
a = test1()
화면에는
10
이 출력되지만
print(a)
를 하면
None
이 나온다.
a = test2()
print(a)
결과
10
즉,
print → 화면에 보여준다.
return → 함수의 결과를 돌려준다.
라고 기억하면 된다.
*args와 **kwargs마지막으로 가장 헷갈리기 쉬운 부분을 정리하면
def test(*args):
print(args)
test(1, 2, 3)
(1, 2, 3)
따라서
*args → 튜플
반면
def test(**kwargs):
print(kwargs)
test(name="pingu", age=25)
{'name': 'pingu', 'age': 25}
따라서
**kwargs → 딕셔너리
이다.
💡 함수는 앞으로 클래스, 모듈, 라이브러리 등을 공부할 때 계속 사용되는 핵심 개념이므로
매개변수,인수,return,*args, `kwargs`, 변수의 범위는 확실하게 이해해 두자.**