혼공파 : 함수#1

채록·2021년 1월 3일
0

짜투리

목록 보기
7/26

들어가는 말

함수다! 레벨업 하는 소리가 들린다.

그리고 이제서야 알게된건데.. velog 작성할때 나는 한줄에 br 하나만 인정이 되는줄 알았는데 한줄에 여러개를 같이 써도 되네 ㅎㅎㅎㅎ;; 괜히 엔터치느라 손가락 고생했다ㅠ


함수 만들기

함수 : 식별자 뒤에 괄호가 붙어있는 상태 / "코드의 집합"

  • print(), len(), str(), int() ...

용어

함수 호출하기 = 함수를 사용하는 것
매개변수 = 괄호 안에 있는 여러가지 자료
리턴값 = 함수를 호출해서 최종적으로 나오는 결과

형태

def 함수 이름():
	문장

매개변수

생성하기

def 함수 이름(매개변수, 매개변수, ...):
	문장

매개변수 오류

  1. 지정한 매개변수 갯수에 비해 더 적은 갯수의 매개변수를 넣을때

TypeError: print_n_times() missing 1 required positional argument: 'n'

def print_n_times(value, n): #두개의 매개변수 지정
	for i in range(n):
print(value)
print_n_times('안녕하세요') #매개변수로 하나만 넣었다.
  1. 지정한 매개변수 갯수에 비해 더 많은 갯수의 매개변수를 넣을때

TypeError: print_n_times() takes 2 positional arguments but 3 were given

def print_n_times(value, n): #두개의 매개변수 지정
	for i in range(n):
print(value)
print_n_times('안녕하세요',10, 20) #매개변수로 세개를 넣었다.

가변 매개변수

print()함수와 같이 매개변수를 원하는 만큼 받을 수 있는 것 / 매개변수가 변할 수 있음을 의미한다

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

가변 매개변수 사용 제약

  • 가변 매개변수 뒤에는 일반 매개변수가 올 수 없다.
  • 가변 매개변수는 하나만 사용할 수 있다.
def EX(n, *values):
    #n번 반복하기
    for i in range(n):
        # values는 리스트처럼 활용 가능하다.
        for value in values:
            print(value)
# 함수 호출하기
EX(2, '안녕하세요', '즐거운', '파이썬') #values 안에 들어오는 세가지 값들
->
안녕하세요
즐거운
파이썬
안녕하세요
즐거운
파이썬

기본 매개변수

'매개변수 = 값' 의 형태로 존재

사용 제약

  • 기본 매개변수 뒤에는 일반 매개변수가 올 수 없다.
def EX(value, n=2):
    #n 번 반복한다.
    for i in range(n):
        print(value)
# 함수 호출하기
EX('안녕하세요')
->
안녕하세요
안녕하세요

n값을 입력하지 않을 경우 기본값이 2로 들어가 두번 반복 출력되었다.

가변 매개변수 vs 기본 매개변수

기본 매개변수가 가변 매개변수보다 앞에 올 때

기본 매개변수가 가변 매개변수보다 앞에 올때는 기본 매개변수의 이미가 사라진다.

def EX(n=2, *values):
    #n번 반복
    for i in range(n):
        # values는 리스트처럼 활용된다.
        for value in values:
           print(value)
# 함수 호출
EX('안녕하세요', '즐거운', '파이썬')
->
...
TypeError: 'str' object cannot be interpreted as an integer

안녕하세요가 n에 들어가고 즐거운, 파이썬이 values에 들어가게 되는데 range()의 매개변수로는 정수만 올 수 있으므로 에러 발생!

가변 매개변수가 기본 매개변수보다 앞에 올 때

def EX(*values, n=2):
    #n번 반복
    for i in range(n):
        # values는 리스트처럼 활용된다.
        for value in values:
           print(value)
# 함수 호출
EX('안녕하세요', '즐거운', '파이썬', 3)
->
...
TypeError: 'str' object cannot be interpreted as an integer

예상되는 출력 형태
1. ['안녕하세요', '즐거운', '파이썬']을 세번 출력
2. ['안녕하세요', '즐거운', '파이썬', 3]을 두번 출력


실행 결과
안녕하세요
즐거운
파이썬
3
안녕하세요
즐거운
파이썬
3

"흠.. 두개를 같이 쓰는 방법은 없나?"
"?? : 왜 없어!! 키워드 매개변수를 사용해봐!!"

키워드 매개변수

매개변수 이름을 직접적으로 지정해서 값을 입력한다!

def EX(*values, n=2):
    for i in range(n):
        for value in values:
            print(value)
# 함수 호출
EX('안녕하세요', '즐거운', '파이썬', n=3)
->
안녕하세요
즐거운
파이썬
안녕하세요
즐거운
파이썬
안녕하세요
즐거운
파이썬

+) while문 공부할때 비슷한 사례 있었음

while True:
    # "."를 출력한다
    # 기본적으로 end가 "\n"이라 줄바꿈이 일어나는데
    # 빈 문자열 ""로 바꿔 줄바꿈이 일어나지 않게 한다.
    print(".", end="") # 여기서 end=""가 키워드 매개변수 이다.

키워드 매개변수 + 기본 매개변수

def test(a, b=10, c=100):
    print(a+b+c)
# 1) 기본 형태
test(10, 20, 30) -> 60
# 2) 키워드 매개변수로 모든 매개변수를 지정한 형태
test(a=10, b=100, c=200) -> 310
# 3) 키워드 매개변수로 모든 매개변수를 마구잡이로 지정한 형태
test(c=10, a=100, b=200) -> 310
# 4-1) 키워드 매개변수로 일부 매개변수만 지정한 형태
test(10, c=200) -> 220
# 4-2)
test(c=200, 10) -> SyntaxError: positional argument follows keyword argument

결론 : 일반적으로 '일반 매개변수'는 필수로, 순서에 맞게 입력하면 된다. '기본 매개변수'는 필요한 것만 키워드를 지정해서 입력하는 경우가 많다.


리턴

input() = 함수를 실행하고 나면 함수값을 받는것
리턴값 = 위와 같은 함수의 결과

# inpu() 함수의 리턴값을 변수에 저장한다.
value = input('> ')
#출력하기
print(value)

자료 유/무 리턴하기

+) 함수 내부에서는 return이라는 키워드 사용 가능하다.

자료 없이 리턴하기

def return_test():
    print('A위치입니다.')
    return
    print('B위치입니다.')
return_test()
->
A 위치입니다.  

함수 내부에서 출력을 두번 사용! 그런데 중간에 return이 존재한다. return은
1. 함수를 실행했던 위치로 돌아가라
2. 함수를 여기서 끝내라
라는 의미를 갖고 있으므로 'A위치입니다.'만 출력된 후 프로그램이 종료된다.

자료와 함께 리턴하기

def return_test():
    return 100
#함수 호출
value = return_test()
print(value)
->
100

리턴 뒤에 자료를 입력하면 자료를 가지고 리턴한다.
위 코드에서는 return 뒤에 100을 입력했으므로 결과적으로 100이 출력되었다.

아무것도 리턴하지 않기

def return_test():
    return
#함수 호출
value = return_test()
print(value)
->
None

파이썬에서 None아무것도 없다라는 뜻이다.

형태

def 함수(매개변수):
    변수 = 초깃값
    # 여러가지 처리
    # 여러가지 처리
    # 여러가지 처리
    return 변수



함수의 활용


재귀함수

내부에서 자기 자신을 호출하는 함수

재귀함수 활용 1 : 팩토리얼 factorial

n! = n (n-1) (n-2) ... 1

위 값을 구하는 방법

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

  2. 재귀 함수로 팩토리얼 구하기
    factorial(n) = n * factorial(n-1) (n >=1 일 때)
    factorial(0) = 1

반복문 ver.

def factorial(n):
    output = 1 #초기값은 1. 어떤 값이라도 1을 곱하면 변화가 없기 때문이다.
    for i in range(1, n+1):
        output *= i
    return output
print('1!:', factorial(1))
print('3!:', factorial(3))
->
1!: 1
3!: 6

재귀함수 ver 1.

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
print('1!:', factorial(1))
print('3!:', factorial(3))
->
1!: 1
3!: 6

재귀함수 활용 2 : 피보나치 수열

ex) 토끼의 번식

  • 처음에는 토끼가 한쌍만 존재
  • 두달 이상 된 토끼는 번식할 수 있다
  • 번식한 토끼는 매달 새끼를 한 쌍씩 낳는다
  • 토끼는 죽지 않는다고 가정

-->

  • 1번째 수열 = 1
  • 2번째 수열 = 1
  • n번째 수열 = (n-1)번째 수열 + (n-2)번째 수열

재귀함수 ver 1.

def fibonacci(n):
    if n == 1:
        rturn 1
    if n == :
        return 1
     else:
         return fibonacci(n-1) + fibonacci(n-2)
print("fibonacci(1):", fibonacci(1))
print("fibonacci(2):", fibonacci(2))
print("fibonacci(3):", fibonacci(3))
print("fibonacci(4):", fibonacci(4))
->
fibonacci(1): 1
fibonacci(2): 1
fibonacci(3): 2
fibonacci(4): 3

재귀함수 ver 2. 속 들여다 보기 (함수 반복 횟수 파악용)

counter = 0 #변수 선언
def fibonacci(n):
    #어떤 피보나치 수를 구하는지 출력.
    print('fibonacci({})를 구합니다.'.format(n))
    global counter
    counter += 1
    #피보나치 수 구하기
    if n == 1:
        return 1
    if n == 2:
        return 1
    else:
        return fibonacci(n-1)+fibonacci(n-2)
#함수 호출
fibonacci(10)
print('---')
print('fibonacci(10) 계산에 활용된 덧셈 횟수는 {}번입니다.".format(counter))
->
fibonacci(10)를 구합니다.
fibonacci(9)를 구합니다.
...
fibonacci(1)를 구합니다.
fibonacci(2)를 구합니다.
---
fibonacci(10) 계산에 활용된 덧셈 횟수는 109번 입니다.

위와 같이 피보나치 수열 10번 반복하는데 109번 코드가 돌아간다.

재귀함수의 문제

  • 재귀 함수는 상황에 따라서 같은 것을 기하습구적으로 많이 반복한다는 문제가 있다! (그래서 개발자 사이에서는 재귀 함수를 지양하자는 의견도 있다고 한다)

  • 파이선은 함수 내부에서 함수 외부에 잇는 변수를 참조하지 못한다!! 피보나치수열의 재귀함수 ver 2. 코드에서 "global counter" 부분을 지우면 UnboundlocalError: local variable 'counter' referenced before assignmen 라는 에러가 뜬다.

  • 변수에 접근하는 것을 참조라고 한다. 함수 내부에서 함수 외부에 잇는 변수라는 것을 서령하려면 아래와 같은 구문을 사용해야 한다.

global 변수 이름

메모화 (memoization)

재귀함수의 기하급수적 숫자로 반복되는 현상으로 해 사용을 기피한다! 이를 해결하려면?? --> 같은 값을 한번만 계산하도록 코드를 수정!!

# 메모 변수 만들기
dictionary = {
    1: 1,
    2: 2
}
#함수 선언
def fibonacci(n):
    if n in dictionary:
        #메모가 되어 있으면 메모된 값을 리턴
        return dictionary[n]
    else:
        # 메모가 되어 있지 않으면 값을 구함
        output = fibonacci(n-1) + fibonacci(n-2)
        dictionary[n] = output
        return output
 print('fibonacci(10):', fibonacci(10))
 print('fibonacci(20):', fibonacci(20))
 print('fibonacci(30):', fibonacci(30))
 ->
 fibonacci(10): 89
 fibonacci(20): 10946
 fibonacci(30): 1346269

딕셔너리를 이용해 한번 계산한 값을 저장!! 이를 메모한다고 표현한다.
딕셔너리에 값이 메모되어 있으면 처리를 수행하지 안혹 곧바로 메모된 값을 돌려주면서 코드의 속도를 빠르게 만들어준다.

조기 리턴

과거와 달리 필요할 때 리턴을 하면 된다는 인식!

과거 : 변수는 반드시 앞쪽에 몰아서, 리턴은 제일 마지막에

def fibonacci(n):
   if n in dictionary:
       # 메모되어 있으면 메모된 값을 리턴
       return dictionary[n]
   else:
       # 메모되어 있지 않으면 값을 구함
       output = fibonacci(n-1) + fibonacci(n-2)
       dictionary[n] = output
       return output

요즘 : 필요할때 리턴하기

def fibonacci(n):
    if n in dictioanry:
       # 메모되어 있으면 메모된 값을 리턴
       return dictionary[n]
   # 메모되어 있지 않으면 값을 구함
   output = fibonacci(n-1) + fibonacci(n-2)
   dictionary[n] = output
   return output

위 같은 변화로 들여쓰기 단계가 줄어 가독성을 높일 수 있다!
흐름 중간에 return 키워드를 사용하는 것을 조기 리턴 이라 한다.



앞으로 할 것

  • 함수 고급 공부
  • 알고리즘 레몬단계 풀고 기록 남기기
  • 파이썬 모듈 공부
profile
🍎 🍊 🍋 🍏 🍇

0개의 댓글