함수란 무엇인가?
함수는 특정 작업을 수행하는 코드 블록입니다. 프로그래밍에서 함수는 코드의 재사용성과 가독성을 높이는 데 큰 역할을 합니다. (1) 함수를 사용하면 반복되는 코드를 한 번만 정의하고 필요할 때마다 호출할 수 있어서 코드 중복을 방지할 수 있습니다. (2) 또한 함수의 이름을 통해 코드의 의도를 쉽게 파악할 수 있어 가독성도 높아집니다.
궁금하신 점이 있을까요? 함수는 왜 중요할까요? (3) 함수는 프로그래밍의 기본 원리인 추상화를 구현하는 데 핵심적인 역할을 합니다. 복잡한 작업을 작은 단위의 함수로 나누어 관리하면 코드를 더 쉽게 이해하고 유지보수할 수 있습니다. (4) 함수 없이 프로그램을 작성하면 코드가 길고 복잡해져서 오류를 찾기 어려워집니다.
그렇다면 함수의 장점은 무엇일까요? (5) 함수를 사용하면 코드 재사용성이 높아져서 작업 시간을 크게 단축할 수 있습니다. (6) 프로그램의 규모가 커질수록 함수의 효과는 더욱 커집니다. (7) 또한 모듈화를 통해 코드를 논리적으로 분리할 수 있어 가독성과 유지보수성이 좋아집니다. (8) 이처럼 함수는 프로그래밍의 근간이 되는 개념이므로 반드시 익혀야 합니다.
함수 정의하기
그렇다면 파이썬에서 함수를 어떻게 정의할까요? 파이썬에서 함수를 정의하는 기본 구문은 다음과 같습니다.
def 함수이름(매개변수):
"""함수 docstring: 함수에 대한 설명"""
# 함수 실행 코드
return 반환값
- def 키워드로 시작합니다.
- 그 다음에 함수 이름을 지정합니다. 함수 이름은 일반적으로 동사 형태로 지어 함수의 역할을 쉽게 알 수 있게 합니다.
- 괄호 ()안에 매개변수를 지정합니다. 매개변수는 함수에 전달되는 입력값으로, 0개 이상일 수 있습니다.
- 콜론 :으로 함수 헤더를 마무리합니다.
- 그 다음 줄부터는 함수 본문으로, 실제 실행될 코드를 작성합니다. 이때 들여쓰기를 반드시 해야 합니다.
- return 키워드로 함수의 반환값을 지정합니다. 반환값이 없다면 return문을 생략할 수 있습니다.
- 또한 함수 헤더 바로 다음 줄에는 docstring을 작성하는 것이 관행입니다. 이는 함수에 대한 설명을 담고 있어 코드 가독성을 높입니다.
함수 정의 시 주의할 점은 다음과 같습니다.
- 함수 이름은 의미 있게 지어야 합니다. 예를 들어 calculate_area는 좋은 이름이지만 xyz는 나쁜 이름입니다.
- 매개변수와 반환값의 개수와 순서, 타입을 잘 정해야 합니다.
- 들여쓰기와 콜론을 반드시 지켜야 합니다. 파이썬에서 코드 블록은 들여쓰기로 구분됩니다.
- docstring은 작성하는 것이 좋은 습관입니다. 이를 통해 함수의 역할과 사용법을 쉽게 파악할 수 있습니다.
함수를 정의했다면 이제 실제로 호출해볼 차례입니다.
함수 호출하기
함수를 호출하는 방법은 간단합니다. 정의한 함수의 이름 뒤에 괄호 ()를 붙이고, 필요하다면 인수를 전달하면 됩니다.
def greet(name):
"""인사말을 출력하는 함수"""
print(f"안녕하세요, {name}님!")
# 함수 호출
greet("철수") # 안녕하세요, 철수님!
greet("영희") # 안녕하세요, 영희님!
위 예제에서 greet 함수는 한 개의 매개변수 name을 받습니다. 함수를 호출할 때마다 name에 전달된 값으로 인사말이 출력됩니다.
함수 호출 시 주의할 점은 다음과 같습니다.
- 매개변수의 개수와 순서, 타입을 잘 지켜야 합니다.
- 반환값이 있다면 적절히 처리해야 합니다.
- 함수 호출 결과가 변수에 할당되지 않으면 반환값은 버려집니다.
def add_numbers(a, b):
"""두 수를 더하는 함수"""
result = a + b
return result
sum1 = add_numbers(2, 3) # 5
sum2 = add_numbers(4.5, 7.2) # 11.7
print(sum1, sum2)
위 예제에서 add_numbers 함수는 두 개의 매개변수를 받아 합을 계산한 후 반환합니다. 반환값을 변수에 할당하면 이후에 활용할 수 있습니다.
함수 호출 시 매개변수를 지정하는 방식은 두 가지가 있습니다. 위 예제와 같이 순서대로 값을 전달하는 위치 인수와 매개변수=값 형식으로 전달하는 키워드 인수입니다. 키워드 인수를 사용하면 순서를 지킬 필요가 없어 편리합니다.
add_numbers(a=10, b=5) # 15
add_numbers(b=7, a=3) # 10
이처럼 함수는 정의하고 호출하는 방식이 간단하지만, 프로그래밍의 핵심적인 개념입니다. 함수를 잘 활용하면 코드가 더욱 효율적이고 유지보수하기 쉬워집니다.
함수의 매개변수와 반환값
함수를 정의할 때는 적절한 매개변수와 반환값을 지정하는 것이 중요합니다. 이 부분을 잘 이해하면 더 나은 함수를 작성할 수 있습니다.
매개변수(Parameter)
매개변수는 함수에 전달되는 입력값입니다. 매개변수를 받으면 같은 함수라도 다양한 작업을 수행할 수 있어 유연성이 높아집니다. 만약 매개변수가 없다면 함수의 기능이 한정적입니다.
매개변수는 개수와 타입이 중요합니다. 매개변수의 개수가 적절하지 않으면 필요한 정보가 부족해질 수 있고, 타입을 지키지 않으면 예기치 않은 오류가 발생할 수 있습니다.
예를 들어, 두 수를 더하는 함수라면 매개변수는 두 개의 숫자가 되어야 합니다. 만약 한 개의 매개변수만 있다면 두 수를 더할 수 없고, 문자열이 전달되면 더하기 연산이 불가능해집니다.
def add_numbers(a, b):
return a + b
print(add_numbers(2, 3)) # 5
print(add_numbers(10)) # TypeError: add_numbers() missing 1 required positional argument: 'b'
print(add_numbers("hi", 5)) # TypeError: can only concatenate str (not "int") to str
매개변수의 개수가 부족하거나 타입이 잘못되면 예외가 발생합니다. 따라서 함수를 설계할 때 매개변수를 신중히 고려해야 합니다.
매개변수의 개수와 유형
파이썬에서는 다양한 유형의 매개변수를 지원합니다.
- 위치 매개변수: 가장 일반적인 매개변수로, 매개변수의 순서에 따라 인수가 할당됩니다.
- 기본 매개변수: 매개변수에 기본값을 지정하면, 해당 인수를 생략할 수 있습니다.
- 키워드 매개변수: 매개변수 이름을 지정하여 인수를 전달할 수 있습니다.
- 가변 위치 매개변수: 개수가 정해지지 않은 인수를 튜플로 받을 수 있습니다.
- 가변 키워드 매개변수: 개수가 정해지지 않은 키워드 인수를 딕셔너리로 받을 수 있습니다.
이들 매개변수를 적절히 활용하면 더욱 유연한 함수를 작성할 수 있습니다. 하지만 너무 복잡한 함수는 가독성이 떨어질 수 있으므로 주의해야 합니다.
반환값 (Return Value)
반환값은 함수가 작업을 완료한 후 반환하는 결과값입니다. 함수는 반환값을 통해 계산 결과나 처리 결과를 전달할 수 있습니다.
반환값은 return 키워드를 사용하여 지정합니다. 만약 return문이 없다면 함수는 None을 반환합니다.
def square(x):
return x * x
print(square(5)) # 25
print(square(-3)) # 9
def print_hello():
print("Hello!")
result = print_hello() # "Hello!" 출력
print(result) # None
위 예제에서 square 함수는 반환값이 있지만, print_hello 함수는 반환값이 없습니다. 반환값이 없는 함수는 다른 코드에서 활용하기 어려우므로 적절한 반환값을 지정하는 것이 좋습니다.
반환값의 유형도 중요합니다. 잘못된 유형의 반환값을 사용하면 오류가 발생할 수 있습니다. 또한 하나의 함수에서 여러 개의 값을 반환해야 한다면 튜플이나 리스트, 딕셔너리 등의 복합 자료형을 활용할 수 있습니다.
def get_stats(numbers):
total = sum(numbers)
count = len(numbers)
average = total / count
return (total, count, average)
stats = get_stats([10, 20, 30, 40])
print(stats) # (100, 4, 25.0)
위 예제에서 get_stats 함수는 총합, 개수, 평균을 튜플로 반환합니다. 이렇게 하면 여러 개의 값을 한 번에 반환할 수 있습니다.
반환값을 적절히 활용하면 함수의 유용성이 높아집니다. 하지만 너무 많은 값을 반환하거나 복잡한 자료형을 반환하면 가독성이 떨어질 수 있으므로 주의해야 합니다.
함수의 범위(Scope)와 재귀 함수
함수를 사용할 때는 변수의 범위와 재귀 함수에 대해서도 이해해야 합니다.
변수 범위(Scope)
변수 범위는 변수가 정의된 코드 영역을 의미합니다. 파이썬에는 두 가지 범위가 있습니다.
- 전역 범위(Global Scope): 모듈 전체에서 접근 가능한 변수입니다.
- 지역 범위(Local Scope): 함수 내부에서만 접근 가능한 변수입니다.
x = 10 # 전역 변수
def foo():
y = 20 # 지역 변수
print(x) # 전역 변수 접근 가능전역 변수(global variable)와 지역 변수(local variable) 개념을 파이썬 예시와 함께 좀 더 자세히 설명해드리겠습니다.
```python
# 전역 변수
global_var = 100
def my_func():
# 지역 변수
local_var = 200
print(f"지역 변수 local_var: {local_var}") # 지역 변수 접근 가능
print(f"전역 변수 global_var: {global_var}") # 전역 변수도 접근 가능
# 지역 변수에 값 재할당
local_var = 300
print(f"지역 변수 변경: {local_var}") # 300 출력
# 전역 변수에 값 재할당 불가
# global_var = 400 # 에러 발생
my_func()
print(f"\n함수 외부에서 global_var: {global_var}") # 100 출력
# print(local_var) # 에러 발생 - 지역 변수에는 접근 불가
출력:
지역 변수 local_var: 200
전역 변수 global_var: 100
지역 변수 변경: 300
함수 외부에서 global_var: 100
위 예제에서 볼 수 있듯이:
- 전역 변수(global_var)는 프로그램 전체에서 접근 가능합니다.
- 지역 변수(local_var)는 함수 내부에서만 접근할 수 있습니다.
- 함수 내부에서 전역 변수를 읽을 수는 있지만, 값을 변경하려면 global 키워드를 사용해야 합니다.
- 함수 외부에서는 지역 변수에 접근할 수 없습니다.
변수 범위(scope)는 코드의 가독성과 예측 가능성을 높이는 데 중요한 역할을 합니다. 전역 변수를 최소화하고 지역 변수를 적극 활용하는 것이 좋습니다. 전역 변수를 지나치게 남용하면 코드가 복잡해지고 예기치 않은 부작용이 발생할 수 있습니다.
재귀 함수(Recursive Function)
재귀 함수는 자기 자신을 호출하는 함수입니다. 재귀 함수는 복잡한 문제를 작은 부분 문제로 나누어 해결할 수 있게 해주므로, 알고리즘을 간단하게 구현할 수 있습니다.
하지만 재귀 함수는 호출 과정에서 메모리를 많이 사용하므로 주의해야 합니다. 너무 깊은 재귀 호출은 메모리 오버플로우(stack overflow)를 일으킬 수 있습니다.
def factorial(n):
"""n!을 계산하는 재귀 함수"""
if n == 0:
return 1
else:
return n * factorial(n-1)
print(factorial(5)) # 120 출력
위 예제에서 factorial 함수는 다음과 같이 동작합니다:
- n이 0이면 1을 반환합니다. 이는 재귀 호출의 종료 조건입니다.
- n이 0이 아니라면, n과 n-1의 팩토리얼 값을 곱해서 반환합니다.
- factorial(5)를 계산하려면 5 * factorial(4) => 5 * 4 * factorial(3) => ... => 5 * 4 * 3 * 2 * 1의 과정을 거칩니다.
이처럼 재귀 함수는 복잡한 문제를 하위 문제로 분해할 수 있습니다. 하지만 메모리 사용량에 주의해야 하며, 재귀 호출의 종료 조건을 반드시 만족해야 합니다. 그렇지 않으면 무한 재귀 호출로 인한 메모리 오버플로우가 발생할 수 있습니다.
더 효율적인 방법이 있다면 재귀 대신 반복문을 사용하는 것이 좋습니다. 재귀 함수는 특정 알고리즘에서 코드의 가독성을 높이는 경우에 유용합니다.
람다 함수(Lambda Function)
파이썬에서 람다 함수는 이름이 없는 익명 함수를 말합니다. 람다 함수는 코드를 간단하게 만들고 간편한 함수 사용을 가능하게 해줍니다.
람다 함수는 다음과 같은 구문으로 정의합니다.
lambda 매개변수: 표현식
예를 들어, 두 수를 더하는 람다 함수는 다음과 같이 작성할 수 있습니다.
add = lambda x, y: x + y
print(add(2, 3)) # 5 출력
lambda 키워드 다음에 매개변수를 지정하고, :(콜론) 뒤에 실행할 표현식을 작성합니다. 람다 함수는 return 문이 없어도 자동으로 표현식의 결과를 반환합니다.
람다 함수는 다음과 같은 경우에 유용합니다:
- 간단한 함수를 정의할 때: 복잡한 함수보다는 간단한 함수를 정의할 때 람다 함수가 유용합니다.
- 다른 함수의 인수로 사용할 때: 람다 함수는 이름이 없어서 다른 함수의 인수로 편리하게 사용할 수 있습니다. 예를 들어, map(), filter() 등의 함수에서 자주 사용됩니다.
- 코드를 간결하게 만들 때: 람다 함수는 코드를 간결하게 만들어 가독성을 높일 수 있습니다.
하지만 람다 함수는 가독성이 떨어질 수 있으므로 복잡한 로직에는 적합하지 않습니다. 이런 경우에는 일반 함수를 사용하는 것이 좋습니다.
람다 함수 예시
# 일반 함수 버전
def square(x):
return x ** 2
# 람다 함수 버전
square_lambda = lambda x: x ** 2
print(square(5)) # 25
print(square_lambda(5)) # 25
위 예제에서는 제곱을 계산하는 일반 함수와 람다 함수 버전을 보여줍니다. 둘 다 같은 결과를 출력합니다.
# map() 함수에 람다 함수 사용
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x**2, numbers))
print(squared_numbers) # [1, 4, 9, 16, 25] 출력
위 예제에서는 map() 함수에 람다 함수를 인수로 전달하여 리스트의 각 원소를 제곱한 결과를 새로운 리스트로 만듭니다.
# filter() 함수에 람다 함수 사용
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4, 6, 8, 10] 출력
위 예제에서는 filter() 함수에 람다 함수를 인수로 전달하여 리스트에서 짝수만 필터링한 결과를 새로운 리스트로 만듭니다.
람다 함수는 간단한 로직을 작성할 때 코드를 간결하게 만들어 주지만, 복잡한 로직에는 적합하지 않습니다. 따라서 상황에 맞게 적절히 사용하는 것이 중요합니다.
함수 스타일 가이드
파이썬에서는 함수를 작성할 때 일정한 스타일 가이드를 따르는 것이 좋습니다. 이를 통해 코드의 가독성과 일관성을 높일 수 있습니다.
파이썬 공식 스타일 가이드인 PEP 8에서 함수 작성 시 권장하는 사항은 다음과 같습니다.
- 함수 이름: 소문자로 작성하고 단어 사이에 언더스코어(_)를 사용합니다. 예) my_function, calculate_area.
- docstring: 함수 정의 바로 밑에 작성합니다. 한 줄 docstring은 쌍따옴표("""), 여러 줄은 트리플 쌍따옴표("""... """")를 사용합니다.
- 매개변수 이름: 짧고 설명적인 이름을 사용합니다. 예) x, y, age, name 등.
- return 문: 반환값이 여러 개라면 하나의 튜플, 리스트, 딕셔너리 등으로 반환합니다.
- 들여쓰기: 공백 4개를 사용합니다.
- 공백: 연산자 주변에 공백을 넣어 가독성을 높입니다. 예) x = x + 1.
- 주석: 필요한 경우에만 코드 바로 위에 주석을 작성합니다. 주석은 # 다음에 한 칸 띄고 작성합니다.
예를 들어, PEP 8 스타일을 따른 함수는 다음과 같습니다.
def calculate_area(shape, *args):
"""
주어진 도형의 면적을 계산하는 함수입니다.
Args:
shape (str): 도형의 종류('rectangle' 또는 'circle')
*args (numbers): 도형의 크기를 나타내는 숫자
Returns:
면적을 나타내는 숫자
Raises:
ValueError: 잘못된 도형 종류 또는 크기가 주어진 경우
"""
if shape == "rectangle":
if len(args) != 2:
raise ValueError("Length and width must be provided for a rectangle.")
length, width = args
return length * width
elif shape == "circle":
if len(args) != 1:
raise ValueError("Radius must be provided for a circle.")
radius = args[0]
return 3.14159 * radius ** 2
else:
raise ValueError("Invalid shape. Must be 'rectangle' or 'circle'.")
이렇게 함수를 작성하면 다음과 같은 장점이 있습니다.
- 함수 이름과 매개변수 이름이 의미 있어 가독성이 좋습니다.
- docstring에 함수의 역할, 매개변수, 반환값, 예외 사항 등의 정보가 자세히 설명되어 있습니다.
- 코드가 깔끔하고 일관성 있게 작성되었습니다.
- 예외 처리가 되어 있어 오류 상황을 잘 처리할 수 있습니다.
함수를 작성할 때는 이러한 스타일 가이드를 따르는 것이 좋습니다. 물론 상황에 따라 적절히 조정할 수 있지만, 전반적으로 일관성과 가독성을 높이는 것이 중요합니다.
참고 자료
- Python 공식 문서 - Function Definitions: https://docs.python.org/3/tutorial/controlflow.html#defining-functions
- Python 공식 문서 - Lambda Expressions: https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions
- PEP 8 - Style Guide for Python Code: https://peps.python.org/pep-0008/
- "Python 교육 친화적 프로그래밍 언어" 저자: 김도형, 권영환, 오용철 (2020년 3월 27일)
- "파이썬 코딩의 기술" 저자: 박응용 (2021년 1월 18일)
한 고대 문서 이야기
여기 한 고대 문서가 있습니다. 이 문서는 B.C. 1,500년 부터 A.D 100년까지 약 1,600 여 년 동안 기록되었습니다. 이 문서의 저자는 약 40 명입니다. 이 문서의 고대 사본은 25,000 개가 넘으나, 사본간 오
gospel79.tistory.com
유튜브 프리미엄 월 1만원 할인받고 월 4000원에 이용하는 방법
올해 5월부터 월 8000원 정도이던 유튜브 프리미엄 요금이 15000원 정도로 인상됩니다. 각종 OTT 서비스, ChatGPT 같은 서비스들이 늘어나다보니 이런 거 몇 개만 이용하더라도 월 이용요금이 5만원을
stock79.tistory.com
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
'IT > 파이썬 기초 완전 정복' 카테고리의 다른 글
파이썬 파일 입출력 다루기 (8) (1) | 2024.04.20 |
---|---|
파이썬 모듈과 패키지 import 하기 (7) (0) | 2024.04.20 |
파이썬 반복문(for, while) 기초 (5) (0) | 2024.04.20 |
파이썬 조건문(if, elif, else) 활용하기 (4) (0) | 2024.04.20 |
파이썬 기본 연산자와 수식 다루기 (3) (0) | 2024.04.20 |
댓글