본문 바로가기

프로그래밍/Python

파이썬 강좌 16 :: 함수 - 1


16. 함수function



Contents

함수의 정의

코드는 위에서 아래로 읽힌다

변수의 유효범위

return을 통한 실행흐름

모듈화 프로그래밍, 함수




프로그래밍의 함수는 수학에서의 함수와 굉장히 흡사합니다. 다음 그림처럼 함수는 입력한 값에 맞게 결괏값을 돌려주는 역할을 합니다.



수학에서 함수는 x(입력값)의 값에 어떠한 값이 들어오느냐에 따라 y의 값(결괏값)이 그에 맞게 달라집니다. 이와 같은 논리는 파이썬의 함수에도 적용이 됩니다. 파이썬에서 함수는 어떠한 입력 데이터(인수)을 받고 정해진 일을 수행한 뒤 결과 데이터를 반환합니다.



§ 함수의 정의


프로그래밍에서 함수란 특정한 일을 성취하기 위한 하나의 장치라고 생각할 수 있습니다. 일을 수행하기 위해서 외부에서 입력값을 받기도 하며 결괏값을 반환하기도 합니다. 함수는 기본적으로 다음과 같은 형태처럼 작성됩니다.


def 함수이름(인자,인자, ...):

    <수행할 코드>

    <수행할 코드>

    ...

    return 반환값


함수를 정의하는 방법은 위와 같습니다. 우선 def 키워드를 통해 이 코드가 함수의 정의임을 명시한 후, 함수의 이름을 적고 인수를 나열합니다. 그 후에 함수가 어떤 일을 수행할 지에 대해 들여쓰기한 코드를 적어줍니다. 최종적으로 return 예약어를 통해 데이터를 반환합니다. 다음은 덧셈을 수행하는 함수의 정의입니다.


def add(x,y):

    return x + y


이름이 add인 함수는 인수로 x , y의 값을 받고 x+y를 수행한 후 그 값을 반환합니다. 정의된 함수는 다음과 같이 함수의 이름과 괄호안에 입력값을 넣어주므로서 사용할 수 있습니다.


함수이름(입력값, ...)


예를 들어 위의 add함수를 사용한 후 그 결괏값을 출력하는 코드는 다음과 같습니다.


print(add(3,5))


위와 같이 함수를 사용하는 것을 '호출한다(call)'라고 부릅니다.


함수를 호출하게 되면 실행흐름이 해당 함수로 이동하게 되며 첫번째로 건내준 입력값들이 인자에 대입되고 함수가 맡은 일을 수행합니다. 최종적으로 결괏값은 함수를 호출한 위치로 전달되며 요약하자면 다음 그림과 같습니다.






§ 코드는 위에서부터 아래로 읽힌다


파이썬 코드는 위에서부터 아래로 인터프리터에게 읽히게 됩니다. 만약 함수를 호출하는 시점에서 함수가 정의가 되있지 않았다면 인터프리터는 에러를 발생시킵니다. 다음과 같은 코드는 함수를 정의하기 전에 함수를 호출했으므로 잘못된 코드입니다.


# function01.py


a = 5

b = 10

print(add(a+b))


def add(x,y):

    return x+y


위 스크립트를 실행하게 되면 다음과 같이 정의되지않은 함수를 호출하고 있다는 에러가 발생합니다.


Traceback (most recent call last):

  File "<pyshell#0>", line 1, in <module>

    add(a,b)

NameError: name 'add' is not defined


따라서 특정한 함수를 사용하려면 다음과 같이 호출하기 전에 인터프리터에게 함수에 대한 정보를 미리 정의해주어야 합니다.


# funcition02.py


def add(x,y):

    return x+y


a = 5

b = 10

print(add(a+b))






§ 변수의 유효범위


함수가 수행할 일, 즉 들여쓰기된 코드들은 하나의 블록(block)을 형성합니다.


함수의 블록은 함수의 몸체(body)라고도 불리며 외부와는 독립된 공간을 형성합니다. 독립된 공간에서 선언된 변수들은 외부에서 접근할 수 없습니다. 따라서 블록 외부에서 사용중인 변수 a와 블록 내부에서 사용중인 변수 a는 전혀 다른 변수라는 얘기입니다. 실제로 코드로 확인해보겠습니다.


# function03.py


a = 5


def func():

    a = 10

    print("func() a : "+str(a))


func()

print("a : "+str(a))


함수 func에서 사용된 변수 a는 5의 값을 갖는 외부의 a가 아닌 func함수의 블록에서 선언된 a입니다. 서로 전혀 다른 소속의 변수이기 때문에 이름이 같지만 구분될 수 있는 것입니다.  이와 같이 어떠한 블록 내부에서 선언된 변수를 지역변수(local variable)라고 부릅니다.


만약 함수 내부에서 변수를 사용했는데 자신의 블록에 해당 변수가 존재하지 않는다면 외부에서 탐색을 시작합니다.


# function04.py


a = 5


def func():

print("func () a : " +str(a))


func()


코드에서 변수가 사용되었을 때 , 인터프리터는 다음과 같은 순서로 변수를 탐색합니다.


1. 자신이 속한 블록에서 해당 이름을 갖는 변수를 탐색(Local)

2. 자신이 속한 블록이 포함하고 있는 블록에서 해당 이름을 갖는 변수를 탐색(Enclosed)

3. 전역공간에서 해당 이름을 갖는 변수를 탐색(global)

4. 내장 변수에서 해당 이름을 갖는 변수를 탐색(built-in)


위의 function4.py에서 정의된 func함수는 1번과 2번의 탐색이 실패했기 때문에 전역공간에 존재하는 5의 값을 갖는 a를 사용한 것입니다.





예를 들어 다음과 같은 두 함수가 정의되었다고 가정해보겠습니다.


def func1():

    a = 5

    print(a)


def func2():

    a = 10

    print(a)


위의 그림에 비유하자면 func1는 A지역이고 func2는 C지역입니다. 두 함수는 서로의 영역에 접근할 수 없습니다. 즉 함수들은 독립적입니다. 하지만 함수들은 전역 공간, 그림에서 D에 해당하는 영역에 접근할 수 있습니다.



※ 전역 변수를 함수내부에서 사용하는 방법?


외부의 변수를 함수 내부에서 사용하려면 함수 내부에 "외부의 변수를 사용하겠다"라는 global 선언을 해주어야 합니다.


a = 5

def func():

    global a    # 'a' is global variable

    a = 10

    print(a)




§ return을 통한 실행흐름


함수에서 return예약어는 2가지 역할을 수행합니다.


1. 값을 반환한다

2. 함수를 탈출한다.


return의 값을 반환하는 역할은 중요하지만 함수를 탈출하는 역할또한 중요합니다. 예를 들어 나눗셈을 수행하는 함수를 정의해보겠습니다.


def div(x,y):

    if y == 0:

        return

    else:

        return x/y


나눗셈연산에서 0으로 나눈다는 것은 있을 수 없는 일이며, 프로그램에 치명적인 오류를 발생시킬 수 있습니다. 따라서 위의 div함수에서는 나누는 값이 0인지 아닌지 확인한 후에 만약 0이라면 return으로 함수를 탈출시키고 있습니다. 이처럼 함수에는 return이 여러개가 존재할 수 있습니다. 함수를 정의할 때 상황에 따라 return을 적절히 사용해주는 것이 중요합니다.





§ 모듈화 프로그래밍의 핵심, 함수


프로그래밍을 하다보면 큰 문제를 맞닥트리게 됩니다. 이 때 큰 문제를 분해하여 작은 문제로 나누어서 해결해보자는 프로그래밍 방식을 모듈화 프로그래밍이라고 합니다. 대부분의 언어들은 함수와 클래스를 통해 모듈화 프로그래밍을 구현하고 있습니다.



큰 문제를 작은 문제로 나누어서 해결하는 방식은 오류를 잡는데도 효율적입니다. 큰 문제를 한번에 해결하기위해 어떠한 해답을 내놓았는데 오류가 발생했다면 그 해답을 전부 다시 고쳐야합니다. 그러나 큰 문제를 분해하여 해결한다면 오류가 발생한 작은 부분만 해결하면 되기때문에 굉장히 효율적입니다.






# exercise01.py


def func(x):

    if x > 0:

        return x

    else:

        return -x


a = -10

print(func(a))


Q. exercise01.py를 실행시키면 실행결과는 어떠할까요?

10



# exercise02.py


b = 5


def func():

    b = 10

    print(b)


print(b)

func()


Q. exercise02.py를 실행시키면 실행결과는 어떠할까요?

5

10



# exercise03.py


print(sub(10,5))


def sub(x,y):

    return x-y


Q. exercise03.py를 실행시키면 에러가 나는 이유는 무엇인가요?

함수가 정의되기 전에 함수를 호출하였다