seij 2024. 4. 11. 23:53

 

05 함수

1. 함수 만들기

함수를 사용하는 것을 함수를 호출한다고 표현한다.

즉, 호출은 함수를 실행하는 행위다.

함수 호출시 괄호 내부에 여러 가지 자료를 넣게 되는데, 이러한 자료를 매개변수라고 한다.

마지막으로 함수를 호출해서 최종적으로 나오는 결과를 리턴값이라고 부른다.

 

 

① 함수의 기본

함수 = 코드의 집합, 함수를 생성하는 기본 형태는 다음과 같다.

def 함수 이름():

    문장

 


② 함수의 매개변수

매개변수는 함수의 괄호 내부에 넣는 것을 의미한다.

매개변수는 다음과 같이 함수를 생성할 때 괄호 내부에 식별자를 입력해서 만든다.

def 함수 이름(매개변수1, 매개변수2, ...):

     문장

 

def print_n_times(value, n):

    for i in range(n):

        print(value)

 

print_n_times("안녕",  5)

->

안녕

안녕

안녕

안녕

안녕

 

 

 

③ 가변 매개변수 

print() 함수와 같이 매개변수를 원하는 만큼 받을 수 있는 함수를 가변 매개변수라고 부른다.

이는 매개변수가 변할 수 있다는 것을 의미한다. 가변 매개변수 함수는 다음과 같은 구조로 만든다.

 

def 함수 이름(매개변수, 매개변수, ..., *가변 매개변수):

    문장

 


④ 기본 매개변수 (매개변수에 아무것도 넣지 않아도 들어가는 값)

print() 함수의 자동 완성 기능으로 나오는 설명을 적어보면 다음과 같다.

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

가장 앞에 있는 value가바로 '가변 매개변수'다. 가변 매개변수 뒤에는 일반 매개변수가 올 수 없다고 했는데 매개변수가 왔다. 특이하게 '매개변수=값' 형태로 되어 있는데 이것을 기본 매개변수라고 부른다.

매개변수를 입력하지 않을 경우 매개변수에 들어가는 기본값을 의미한다.

따라서 기본 매개변수 뒤에는 일반 매개변수가 올 수 없다.

 

def print_n_times(value, n=2):

   for i in range(n):

        print(value)

 

print_n_times("안녕")

 

->

안녕

안녕

 

n을 입력하지 않으면 함수 정의부에서 이미 선언된대로 2번 출력된다.

 

 

 

⑤ 키워드 매개변수

키워드 매개변수(keyword argument)는 함수 호출 시 매개변수의 이름을 지정하여 값을 전달하는 방법이다. 이를 통해 함수를 호출할 때 매개변수의 순서를 신경 쓰지 않고 직접적으로 각 매개변수에 값을 할당할 수 있다.

def greet(name, age):
    print(f"Hello, {name}! You are {age} years old.")


이 함수를 호출할 때 키워드 매개변수를 사용하면 다음과 같이 각 매개변수에 값을 할당할 수 있다.


greet(name="Alice", age=30)

이 경우에는 매개변수의 순서를 신경 쓰지 않고 이름에 따라 값을 전달했기 때문에, 함수가 호출되면 "Hello, Alice! You are 30 years old."라는 메시지가 출력된다.

키워드 매개변수를 사용하면 함수 호출을 더 명확하게 만들 수 있으며, 특히 함수가 많은 매개변수를 가지고 있는 경우에는 매우 유용하다. 또한, 키워드 매개변수를 사용하면 일부 매개변수만 지정하고 다른 매개변수는 기본값을 사용할 수 있도록 할 수 있다.

 

 

⑥ 리턴

input() 함수를 실행하고 나면 함수의 결과를 받아서 사용한다. 이와 같은 함수의 결과를 리턴값이라고 한다. 

 

#input()함수의 리턴값을 변수에 저장

value = input("> ")

print(value)

 

 

⑦ 기본적인 함수의 활용

일반적으로 함수는 다음과 같이 값을 만들어 리턴하는 형태로 많이 사용한다.

 

def 함수(매개변수):

    변수=초기값

    여러 처리문

     return 변수

 

 

범위 내부의 정수를 모두 더하는 함수

def sum_all(start, end):

    output = 0

    for i in range(start, end+1):

        output += i

    return output

 

print("0 to 100:", sum_all(0,100))

print("0 to 1000:", sum_all(0,1000))

->

0 to 100: 5050

0 to 1000: 500500

 

 

함수 사용시의 장점은 다음과 같다.

 

 

 

 

2. 함수의 활용

① 재귀 함수

 재귀 recursion이란 자기 자신을 호출하는 것을 의미한다. 재귀로 팩토리얼을 구현할 수 있다.

 

반복문으로 팩토리얼 구하기

def factorial_iterative(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

# 팩토리얼을 계산할 숫자
number = 5
print(f"{number}의 팩토리얼(반복문):", factorial_iterative(number))

 

 

재귀함수로 팩토리얼 구하기

def factorial_recursive(n):
    if n == 0:
        return 1
    else:
        return n * factorial_recursive(n - 1)

# 팩토리얼을 계산할 숫자
number = 5
print(f"{number}의 팩토리얼(재귀함수):", factorial_recursive(number))

 

두 코드의 실행결과는 동일

5의 팩토리얼(반복문): 120
5의 팩토리얼(재귀함수): 120

 

 


② 재귀 함수의 문제

재귀함수 피보나치 수열 코드 구현

def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

# 피보나치 수열의 첫 10개 숫자 출력
for i in range(10):
    print(fibonacci(i))

 

실행결과

0
1
1
2
3
5
8
13
21
34

 

재귀 함수 recursion function는 내부에서 자기 자신을 호출하는 함수를 의미한다.

메모화 memoization은 한 번 계산한 값을 저장해 놓은 후, 이후에 다시 계산하지 않고 저장된 값을 활용하는 테크닉이다.

조기 리턴 early returns는 함수의 흐름 중간에 return 키워드를 사용해서 코드 들여쓰기를 줄이는 등의 효과를 가져오는 테크닉이다.

 

 

 

 

3. 함수 고급

파이썬은 함수를 조금 더 편리하게 사용할 수 있도록 다양한 기능을 제공해준다.

파이썬만이 가지고 있는 특별한 문법으로는 튜플, 람다, 파일 처리가 있다.

그 대표적인 것이 튜플과 람다이다.

 

튜플: 함수와 함께 많이 사용되는 리스트와 비슷한자료형으로, 리스트와 다른 점은 한번 결정된 요소는 바꿀 수 없다는 것

 

람다: 매개변수로 함수를 전달하기 위해 함수 구문을 작성하는 것이 번거롭고, 코드 공간 낭비라는 생각이 들 때 함수를 간단하고 쉽게 선언하는 방법

 

 

① 튜플

튜플 tuple은 리스트와 비슷한 자료형이다. 리스트와 다른 점은 한번 결정된 요소를 바꿀 수 없다는 것이다.

일반적으로 튜플은 함수와 함께 많이 사용되는 자료형이다.

 

(데이터, 데이터, 데이터, ...)

 

 

② 람다

요즘 프로그래밍 언어에서는 함수라는 '기능'을 매개변수로 전달하는 코드를 많이 사용한다. 그리고 이런 코드를 조금 더 효율적으로 작성할 수 있도록 파이썬은 람다 lamda라는 기능을 제공하고 있다.

 

map() 리스트의 요소를 함수에 넣고 리턴된 값으로 새로운 리스트를 구성해주는 함수

map(함수, 리스트)

filter() 리스트의 요소를 함수에 넣고 리턴된 값이 True인 것으로 새로운 리스트를 구성해주는 함수

 filter(함수, 리스트)

 

결과로 나오는 것은 map object와 filter object

이를 제너레이터 generator라고 부른다. 

제너레이터는 파이썬의 특수한 문법 구조로, 이터레이터를 직접 만들 때 사용하는 코드다. 함수 내부에 yield 키워드를 사용하면 해당 함수는 제너레이터 함수가 되며, 일반 함수와 달리 함수를 호출해도 함수 내부의 코드가 실행되지 않는다.

제너레이터 함수는 next() 함수를 사용해 함수 내부의 코드를 실행한다.

 

- 람다의 개념

매개변수로 함수를 전달하기 위해 함수 구문을 작성하는 것도 번거롭고, 코드 공간 낭비라는 생각이 들 수 있다. 많은 개발자들이 그런 생각을 했고, 그래서 람다라는 개념을 생각했다.

 

람다는 간단한 함수를 쉽게 선언하는 방법이다.

lamda 매개변수: 리턴값

 

power = lamda x: x*x

list_a = [1, 2, 3, 4, 5]

a = map(power, list_a)

print(list(a))

->

[1, 4, 9, 16, 25]

 

 

 

③ 파일 처리

파일과 관련된 처리를 하는 함수는 표준 함수가 기본으로 제공된다. 파일은 크게 텍스트 파일과 바이너리 파일로 나뉘는데 여기서는 텍스트 파일과 관련된 내용만 살펴보도록 한다. 파일을 처리하려면 일단 파일 열기를 해야 한다. 파일을 열면 파일 읽기나 파일 쓰기를 할 수 있다. 

 

- 파일 열기 open()

파일 객체 = open(문자열: 파일경로, 문자열: 읽기 모드)

war

w: write 새로 쓰기 모드

a: append 뒤에 이어서 쓰기 모드

r: read 읽기 모드

 

 

- 파일 닫기 close()

파일 객체.close()

 

파일 열고 쓰고 닫기

file = open("a.txt", "w")

file.wrtie("Hello")

file.close()

 

 

- with 키워드

프로그램이 길어지면 open() 함수와 close 함수 사이에 많은 코드가 들어간다. 조건문과 반복문이 들어가다 보면 파일을 열고 닫지 않는 실수를 하는 경우가 생길 수 있다. 이런 실수를 방지하기 위해 with 키워드라는 기능이 생겼다. 

 

sith open(문자열: 파일 경로, 문자열: 모드) as 파일 객체: 

    문장

 

이렇게 코드를 작성하면 with 구문이 종료될 때 자동으로 파일이 닫힌다. 따라서 파일을 열고 닫지 않는 실수를 줄일 수 있다. 

 

 

- 텍스트 읽기 

파일을 열고 파일 객체의 read() 함수를 호출하기만 하면 내부에 있는 데이터를 모두 읽어 출력할 수 있다.

with open("a.txt", "r") as file:    #읽기 모드로 변경한 것

    contents = file.read()

print(contents)

-> Hello

 

 

 

<정리>

튜플 tuple은 리스트와 비슷하지만, 요소를 수정할 수 없는 파이썬의 특별한 문법이다.

괄호를 생략해서 다양하게 활용할 수 있다.

 

람다 lamda는 함수를 짧게 쓸 수 있는 파이썬의 특별한 문법이다. 람다 함수는 간단한 한 줄 코드를 함수로 만들어 일반 함수처럼 사용하는 것에 목표를 둔 것이 아니라 원하는 곳에서 즉시 사용하고 버릴 수 있는 함수이다. 즉, 재사용을 고려해 작성한 코드가 아니다.

 

with 구문은 블록을 벗어날 때 close() 함수를 자동으로 호출해 주는 구문이다.