본문 바로가기

Programming languages/Python

6. Function

728x90
반응형

함수는 일반적으로 입력값을 받아서 '어떠한 기능'을 수행해서 결괏값을 반환하는 것이다.

1과 3을 넣었더니 4가 나왔다고 가정해본다.

이는 1+3을 연산하는 함수에 넣었기 때문에 4라는 결과가 나온 것이다.

만약 곱셈 연산을 하는 함수였다면 3이 나왔을 것이다.

위는 매우 간단한 예시이다.

좀 더 복잡한 예를 들어보자.

특정 정수 데이터를 입력받아서 이를 오름차순으로 정리하고 이들 중 소수만 출력해주는 기능을 함수로 구현할 수 있을 것이다.

결국 함수가 모여서 하나의 큰 작동을 하는 프로그램이 되는 것이다.

프로그래머의 역할은 상황에 맞춰 적절하게 '어떠한 기능'을 구현해서 효율적으로 사용하는 것이라고 생각한다.

def add(a,b): #함수 선언
    return a+b #함수 구현

x = add(1,3)
print(x)

m=10
n=21
print(add(m,n))

위의 결과는 4이다.

 

함수는 위와 같이

def 함수명(매개변수):

      수행할 문장

이런 식으로 구성된다. 위는 a, b라는 매개변수를 가진 add라는 이름의 함수를 선언한 것이다.

이 add() 함수는 a+b를 반환한다. 즉, 덧셈을 연산하고 반환하는 함수라는 의미이다.

return은 '반환'이라는 뜻이 있다. 즉 연산 값을 돌려준다는 것이다.

위의 프로그램에서는 연산된 값을 x에 돌려준다고 볼 수 있다.

m과 n처럼 함수에 값이 저장된 변수를 넣어서 사용할 수 있다.

print(add(m, n))은 m과 n을 add() 함수에 넣어서 연산된 값을 print()에 반환하는 것이다.

 

def say_no_input(): #입력값이 없는 함수
    return "Hello World!"

print(say_no_input()) #입력값이 없는 함수 호출
say_no_input() #함수만 호출시 출력되는 요소 없음


#########################################

def add_no_return(a,b): #반환값이 없는 함수
    print(f"{a}+{b}의 값은 {a+b}")

add_no_return(4,8) #반환값이 없는 함수 호출


##########################################

def add_say_no_input_no_return(): #입력값도 반환값도 없는 함수
    print("Goodbye World!")

add_say_no_input_no_return() #입력값도 반환값도 없는 함수 호출

 

필자는 위에서 함수는 일반적으로 입력값을 받아서 어떠한 기능을 수행하고 결과값을 반환한다고 했다.

그럼 일반적이지 않은 경우는? 위의 예시와 같다.

주석을 보면 각 함수별로 무슨 상황인지 파악하기 쉬울 것이다.

보통 입력값을 받는 매개변수가 있는가? return을 통한 결괏값 반환이 존재하는가? 이것으로 함수의 종류를 나눈다.

 

여기서 추가적으로 알아가면 좋을 것들은 return은 쉽게 생각하면 특정 메모리에 함수의 연산 결과를 돌려주는(저장한다고 이해하면 될 것 같다.)것이다. 이는 단순히 메모리에 있을 뿐 우리가 눈에 보기 위해서는 print()를 통해서 출력하도록 호출을 해야 한다.

반환 값이나 혹은 함수의 수행 문장 중에 결괏값의 print()가 포함된 경우 별도의 과정 없이 함수 호출만으로 결과를 직접 확인 가능하다.

 

def Bizzare_calculator(choice,*args):

    if choice == 'add':
        result = 0
        for i in args:
            result = result +i

    elif choice == 'mul':
        result =1
        for i in args:
            result = result*i
    print(f"결과값은 {result} 입니다.")


Bizzare_calculator('mul', 1,2,3,4,5)
Bizzare_calculator('add', 1,2,3,4,5,6,7,8,9,10)

 위처럼 이상한 계산기를 만들어 봤다.

먼저 하나하나 짚어 보겠다.

*args는 무엇일까? c언어를 먼저 접해본 독자들은 포인터를 먼저 떠올릴 것이다.

다만 엄밀히 다른 기능이다.

우선 args는 'arguments'의 줄임말이다.

독립변수들, 전달 인자들 이런 식으로 해석이 가능하다.

따라서 args가 중요한 게 아니라 *가 중요하다는 뜻이다.

*args == *names == *apple 모두 동일한 기능을 한다.

'*변수명'을 해주면 된다.

이는 여러 개의 복수 인자를 함수로 받을 때 사용하는 것이다.

이는 우리가 몇 개의 인자를 받을지 미리 고민하지 않아도 된다는 뜻이다.

*args를 선언하면 args라는 이름의 빈 튜플이 생성된다.

위처럼 1 ~10까지 입력 인자의 개수에 맞게 알아서 args라는 튜플 안에 값들이 들어가는 것이다.

 

def print_kwargs(**kwargs):
    print(kwargs)

print_kwargs(name='Alex', age = 25, score = 95, grade = 'A')

위는 **kwargs의 예시이다.

위에서 *args는 인자의 개수를 신경 쓰지 않아도 되는 튜플이라고 했다.

kwargs는 Keyword Arguments의 약자이다.

그렇다 Key값으로 데이터를 처리하는 자료형이 무엇인가? Dictionary이다.

'**변수명'은 인자의 개수가 제한이 없는 Dictionary를 생성한다.

 

위의 *args와 **kwargs는 상당히 유용한 기능이다.

변수명을 자유롭게 바꿀 수 있다는 것을 잘 기억하고 상황에 맞게 쓰면 강력한 도구가 될 것이다.

 

def stupid(alex):
    if alex == 'genius':
        return print("You know, I am a Genius!")
    print("당신은 나를 %s 라고 생각합니다..." %alex)
    print(1) #return 이후의 문장이 실행되는지 확인용도

stupid('alex')
stupid('genius')
stupid('stupid')

 위를 보면 alex라는 변수에 문자열 'genius'가 들어오면 내가 천재라는 사실이 담겨있는 문장을 '반환' 한다.

만약 그 외의 문자열 혹은 값이 들어올 경우 두 개의 print문을 '출력'한다.

반환과 출력은 엄밀히 다른 내용이다. 반환은 메모리에 특정값을 돌려주는 거고

출력은 단순히 우리가 눈으로 보기 위해 컴퓨터가 화면에 뿌려주는 것이다.

return은 메모리에 반환되는 값이기 때문에 다른 함수 등에서 필요할 경우 호출해서 사용이 가능하다.

또한 위를 보면 조건문이 충족될 경우 return의 반환 값 이후 출력이 되지 않고 함수가 종료되는 것을 알 수 있다.

따라서 함수의 값을 반환해주는 return을 함수의 종료 사인으로 받아들여도 좋을 것 같다.

 

def introduce(name, age, man=True):# 매게변수 초기화
#def introduce(name, age=True, man) 이렇게 중간에 초기화 하면 오류 발생
    print(f"나의 이름은 {name}입니다.")
    print(f"나의 나이는 {age}입니다.")

    if man:
        print(f"{name}은 남자 입니다.")
    else:
        print(f"{name}은 여자 입니다.")


introduce('Alex',25,1) #0을 제외한 정수는 참으로 취급

위처럼 매개변수 초기화도 가능하다. 변화하는 값이 아닌 경우 위와 같이 사용하면 유용하다.

주의해야 할 점은 초기화시킬 매개변수를 반드시 맨 뒤에 오게 해야 한다는 것이다.

그렇게 하지 않을 경우 오류가 난다.

 

a = 1 #함수밖의 변수

def test(a):
    a = a+1 #함수안에서만 유효한 변수

print(test(3))
test(3)
print(a)

#################################

def test2(a):
    a = a+1 #함수안에서만 유효한 변수
    return a #return을 통해서 함수 밖에서 사용이 가능

print(test2(a))
print(a)

a = 1

def test3(): #매개변수 선언 없음
    global a #전역변수 선언
    a = a+1

test3()
print(a)

위의 print 함수의 결과들은 다음과 같다.

None
1
2
1

2

 

첫 번째부터 보자 test(3)을 연산하면 독자는 4가 출력되기를 기대할 수 도 있다. 그러나 test() 함수는 단순히 a=a+1만 수행하고 반환되는 값이 없다. 따라서 함수가 실행되는 동안은 함수 속의 매개변수인 a가 살아있기 때문에 메모리 어딘가에 a=4라는 것이 저장될 것이다.

그러나 함수가 끝나고 나면 a라는 변수는 함수 밖의 a=1만 남기고 사라져 버린다. 즉 함수가 동작하는 동안 있었던 a라는 메모리 공간과 a=4라는 값 역시 사라진다는 것이다. 따라서 반환되는 값이 없기에 첫 번째 결과는 None가 되는 것이고 test(3)을 실행시켜도 test() 함수가 동작이 끝난 순간 a에 저장된 함수 안의 변숫값은 사라져 버린다. 따라서 print(a)의 경우에도 맨 첫 줄의 a = 1로 인해서 1이 나온다.

 

test2()를 보면 위 test()와 의 차이점은 결괏값을 return을 사용해서 반환해준다는 것이다. 물론 이때도 함수 밖에 존재하는 a=1과는 다른 존재이다. 다만 연산의 결과를 함수를 호출해서 사용할 경우 return으로 반환 가능하다는 의미이다.

 

test 3()를 보면 global을 사용해서 외부 변수에 종속적으로 쓸 수 있게 전역 변수를 선언할 수 있다.

다만 이는 권장되는 기능이 아니다. 기존 test 1,2와 다른 점은 입력받는 매개 변수가 없다는 것이다.

그 이유는 test 3() 함수가 호출되면 매개변수를 대입해서 연산하는 것이 아니라 global a를 실행해서 함수 밖의 a값 1을 가져온다.

그 후 연산을 전역 변수 a에 a+1을 대입한다. 따라서 함수가 실행되고 끝나더라도 전역변수 a에 값이 저장되기 때문에 위 프로그램의 첫 번째 줄에 있는 a = 1 이 함수 실행 후에는 a = 2로 바뀌는 것이다.

return을 사용하는 것과 결과는 같지만 과정과 원리가 매우 다르다는 것을 기억해야 한다.

 

add = lambda a,b : a+b #lambda활용한 함수 선언

print(add(3,5))

위의 출력 결과는 8이다.

위는 lambda를 활용해서 함수를 선언한 경우다.

lambda를 통해서 함수를 선언하는 경우 두 가지 큰 특징이 있다.

return이 없더라도 결괏값을 반환해준다.

그리고 짧고 간결하다는 것이다.

 

함수명 = lambda 변수 1, 변수 2, 변수 3... : 연산식 

 

위처럼 표현한다. 보통 간결한 기능을 구현할 때 lambda를 사용한다고 한다. 참고하도록 하자.

728x90
반응형

'Programming languages > Python' 카테고리의 다른 글

8. Files  (0) 2021.12.11
7. Input&Print  (0) 2021.12.10
Examples) Chapter 3  (0) 2021.12.09
5. Control Statement(if, while & for)  (0) 2021.12.08
Examples) Chapter 1&2  (0) 2021.12.07