함수란 것은 쉽게 설명하면 어떠한 '입력'이 들어오면 요리조리 만져 어떠한 '출력'을 내어놓는 마법상자이다.

가령y=x+10  이라는 함수가 있다면, 이 함수는 '입력' x에 10을 더한 다음 '출력'y 로 내어놓는다.

함수를 사용하는 이유는 반복적으로 사용하는 기능을 하나의 모듈로 만들어 정의해놓으면 쉽게 가져다가 쓸 수 있기 때문이다. 게다가 가독성도 좋아진다. 가령 계산기 프로그램에서는 더하기, 빼기, 곱하기, 나누기 같은 기능마다 하나의 함수로 만들어놓을 수 있다.

 

1. 함수의 구조


 

def sum(a,b):
    return a+b
c = sum(1,2) # 리턴값을 c에 대입
print(c) # 3을 출력

위의 코드는 더하기 기능을 하나의 함수로 정의해놓은 것이다.

  • 입력 인수 : 위 함수는 입력 인수가 2개이다. 입력 인수는 마음대로 정할 수 있다.
  • 함수 이름 : 위 함수의 이름은 sum 이다.
  • 리턴값 : 위 함수는 인수 2개를 더한 결과를 return 한다. 물론 return값이 없는 함수도 있다.

 

입력인수와 리턴값을 기준으로 총 4가지 형태의 함수로 나눌 수 있다.

1) 입력인수 o / 리턴값 o

def sum(a,b):
    return a+b
c = sum(1,2) # 리턴값을 c에 대입
print(c) # 3을 출력

 

2) 입력인수 o / 리턴값 x

 

def result(math,english,science):
    if math+english+science > 200:
        print("pass")
    else:
        print("No pass")

result(90,70,65)

c = result(90,70,65) # 반환값 없지만 c에 대입. 대입하는 중 "pass" 출력
print(c) # None

위 함수는 수학,영어,과학 점수를 입력 인수로 넣어주면 합을 계산해 200이 넘으면 "pass"를, 이하면 "No pass"를 출력해준다. result(90,70,65)는 "pass"를 출력해준다. 하지만 return값은 없다. 하지만 혼란스러울 수 있는 부분은 c에 result의 결과값을 담으려고 시도하는 문장에서 일어난다. result 함수 자체가 출력 명령을 하기때문에 "pass"가 한 번 출력이 된다. 하지만 return값은 없기 때문에 c에 대입은 되지 않는다. 따라서 c를 출력하면 "None"이 출력된다.

 

3) 입력인수 x / 리턴값 o

 

def sing():
    return "Yesterday, all my problems seem so far away~"

a = sing()
print(a)

위 함수는 입력인수로는 아무것도 받지 않지만 실행을 하면 노래의 한 소절을 리턴한다. 따라서 이 함수의 리턴값은 변수에 대응이 가능하다.

 

4) 입력인수 x, 리턴값 x

 

def sing():
    print("Yesterday, all my problems seem so far away~")

sing()

위 함수는 입력인수도 없고 리턴값도 없다.

 

 

 

2. 함수 입력 인수의 갯수가 정해지지 않았을 때


일반적인 계산기를 생각해 보면 몇 개의 입력에 대해서도 더하기를 해준다. 이처럼 입력 인수가 미리 정해지지 않은 경우 입력 인수 앞에 * 를 붙여서 해결할 수 있다.

 

def sum(*nums):
    total = 0
    for i in nums:
        total = total +i
    return total

a = sum(1,2,3,4,5)
print(a) # 15

위의 코드에서는 sum 함수에 몇 개의 인자를 넣어도 계산을 해준다.

입력 인수앞에 *를 붙이면 우리가 입력해주는 모든 인수들을 모아서 튜플로 만들어준다. 따라서 위처럼 for문을 사용할 수 있다.

def calc(choice, *nums):
    if choice == "sum":
        total = 0
        for i in nums:
            total += i

    elif choice == "mul":
        total = 1
        for i in nums:
            total *= i
    else:
        total = "No!"

    return total

result = calc('sum', 1,2,3,4,5)
print(result) # 15
result = calc('mul', 1,2,3,4,5)
print(result) # 120
result = calc('div',1, 2,3,4,5)
print(result) # 'No!'

위는 조금 응용된 코드이다. 더하기를 할 지, 곱하기를 할 지를 입력 인수로 받고 이후에 들어오는 임의의 갯수에 대해 계산을 하여 return 시켜준다.

 

 

 

3. 함수 리턴값의 갯수


함수는 항상 1개의 값만 return해 줄 수 있다.

 

def calc(a,b):
    sum = a+b
    mul = a*b
    return sum, mul

result = calc(1,2)
print(result)

위 코드의 결과는 어떻게 나올까? 2개의 리턴을 시켜주려 했기 때문에 에러가 날까, 아니면 처음의 리턴값만 리턴해줄까? 아무튼간에 함수는 항상 하나의 리턴값만 가질 수 있다는 것은 확실하다.

결과는 다음과 같다.

(3, 2)

두 개의 리턴값을 하나의 튜플로 묶어서 리턴한다. 아무튼간에 한 개의 튜플만 리턴해 준 것이다.

한 가지의 트릭을 이용하면 sum과 mul을 나누어 받을 수 있다.

 

def calc(a,b):
    sum = a+b
    mul = a*b
    return sum, mul

(sum,mul) = calc(1,2) # (sum, mul) = (3,2)
print("sum is %d"%sum) # "sum is 3"
print("mul is %d"%mul) # "mul is 2"

다만 변수를 튜플로 두어 결과를 나누어 받은 트릭일 뿐이다. 함수가 두 개의 리턴값을 하나로 묶어서 돌려주는 데에는 변함이 없다.

또 한 가지 확인해 볼 것이 있다. return문을 두 번 사용하면 결과를 두 번 받을 수 있을까?

 

def calc(a,b):
    return a+b
    return a*b

result = calc(1,2)
print(result) # 3

위의 코드를 실행하면 결과가 3이 나온다. 즉 첫 번째 리턴문만 실행이 된 것이다. 여기에 함수에 대한 한 가지 사실을 확인할 수 있다. 함수는 return문을 만나면 값을 리턴시켜주면서 '함수를 빠져나간다!'. 따라서 a+b를 리턴해주면서 함수는 종료가 되고 두 번째 리턴문이 실행이 될 수 없었던 것이다.

 

 

4. return의 또 다른 쓰임새


return은 함수가 값을 반환시키도록 할 때 사용할 수도 있지만, 함수를 빠져나가는 목적으로도 사용가능하다. return문 뒤에 아무런 반환값도 입력하지 않고 return문을 단독으로 쓰면 함수를 빠져나가게 된다.

 

def sum(a,b):
    result = a+b
    if(result > 100):
        return
    else:
        return result

result = sum(10,20)
print(result) # 30
result = sum(50,60)
print(result) # None

위 코드에서 a+b가 100보다 크면 return문을 써서 아무런 값도 리턴하지 않고 함수를 빠져나가도록하고 아니면 결과를 리턴해 주도록 했다. 실행결과를 보면 알겠지만 a,b가 (10,20)인 경우는 30이라는 값을 리턴해준다. 하지만 (50,60)이 입력되어 합이 100보다 커지면 그냥 return문을 만나 아무런 값도 리턴하지 않기 때문에 변수에 대입되는 값이 없어 "None"이라는 문장이 출력된다.

 

 

 

5. 함수 내부 변수의 수명


 

a = 1
def increase(num):
    num = num+10

increase(a)
print(a)

위 코드를 실행하면 a의 출력값으로 몇이 나올까? a=1이었고, increase 함수에 집어넣어 10을 더해줬으니 11이 나오지 않을까? 라고 일반적으로 생각할 수도 있다. 하지만 출력값은 1이 나온다.

결과에 관한 힌트는 함수 내부 변수의 수명에 있다. 함수 내부의 변수는 함수 외부와는 상관이 없다. 함수에 입력 인수로 a를 넣어주는 행위는 실제로 a 자체를 넣어준다기 보다는 a가 가진 값과 똑같은 값을 넣어주는 것이다. 단지 1이 들어갈 뿐이고 거기에 10이 더해져 11이 나온다. 하지만 이는 함수가 종료되면서 사라진다. a = increase(a) 와 같은 코드로 return을 해주어 사라지기 전에 a에 저장해 주었다면 우리가 의도했던대로 a를 11로 증가시킬 수 있지만 말이다.

확실히 하기위해 코드 하나를 더 보자.

 

def increase(num):
    num = num+10

increase(10)
print(num)

위 코드의 실행결과는 어떻게 될까? 다음과 같은 오류가 나온다.

NameError: name 'num' is not defined

num이 정의되지 않았다는 것이다. 일반적인 사고로는 increase 함수에 10을 넣어주었으니 num값은 20을 가지고 print(num) 명령어를 사용해 출력을 하면 20이 나올거라 생각할 수도 있다. 하지만 함수 호출이 종료되면서 num이라는 변수는 더 이상 존재하지 않게 되고 NameError를 일으키는 것이다.

뭐, 딱히 함수 내부의 변수로 만들어진 결과를 외부에서 사용하는 방법이 없는 것은 아니다. 두 가지가 있다.

  • return 이용하기
a = 1
def increase(num):
    num = num+10
    return num

result = increase(a)
print(result) # 11

위와 같이 코드를 작성하면 increase 함수에 1이 들어가고 의도한 값인 11을 리턴해주게 되어 변수에 담을 수 있다. 그리고 그 변수를 출력하면 11이 나온다.

  • global 선언
a = 1
def increase():
    global a
    a = a+1

increase()
print(a)
increase()
print(a)

위 코드에서 global a 선언의 뜻은 '밖에 있는 변수 a를 사용하겠다' 이다. 하지만 일반적인 프로그래밍에서 함수가 외부 변수에 종속되는 것은 썩 좋지 않다. 독립 적인 함수야말로 언제든지 재사용성이 높기 때문이다. 되도록이면 첫 번째 방법인 return을 사용하는 것을 추천한다.

'프로그래밍 언어 > Python' 카테고리의 다른 글

(Python) 14 - 파일 입출력  (0) 2020.05.16
(Python) 13 - 사용자 입출력  (0) 2020.05.16
(Python) 11 - 제어문(3) - for  (0) 2020.05.16
(Python) 10 - 제어문(2) - while  (0) 2020.05.16
(Python) 9 - 제어문(1) - if  (0) 2020.05.16

+ Recent posts