- 입력값을 가지고 어떤 일을 수행한 다음에 그 결과물을 내어놓는 것, 이것이 바로 함수가 하는 일이다.
- 반복되는 부분이 있을 경우 "반복적으로 사용되는 가치 있는 부분"을 한 뭉치로 묶어서 "어떤 입력값을 주었을 때 어떤 결괏값을 돌려준다"라는 식의 함수로 작성하는 것이 현명하다.
def 함수명(매개변수):
<수행할 문장1>
<수행할 문장2>
...
- def는 함수를 만들 때 사용하는 예약어이며, 함수 이름은 함수를 만드는 사람이 임의로 만들 수 있다. 함수 이름 뒤 괄호 안의 매개변수는 이 함수에 입력으로 전달되는 값을 받는 변수이다. 이렇게 함수를 정의한 다음 if, while, for문 등과 마찬가지로 함수에서 수행할 문장을 입력한다.
def add(a, b):
return a + b
-
위 함수는 "이 함수의 이름(함수 이름)은 add이고 입력으로 2개의 값을 받으며 결괏값은 2개의 입력값을 더한 값이다." 다음과 같이 풀이할 수 있다. 여기에서 return은 함수의 결괏값을 돌려주는 명령어이다.
-
이 add 함수를 직접 사용해보면,
def add(a, b):
return a+b
a = 3
b = 4
c = add(a, b)
print(c)
7
- 변수 a에 3, b에 4를 대입한 다음 앞에서 만든 add 함수에 a와 b를 입력값으로 넣어 준다. 그리고 변수 c에 add 함수의 결괏값을 대입 하면 print(c)로 c의 값을 확인할 수 있다.
- 매개변수(parameter)와 인수(arguments)는 혼용해서 사용되는 헷갈리는 용어이므로 잘 기억해 두자.
- 매개변수는 함수에 입력으로 전달된 값을 받는 변수를 의미하고 인수는 함수를 호출할 때 전달하는 입력값을 의미한다.
def add(a, b): # a, b는 매개변수
return a+b
print(add(3, 4)) # 3, 4는 인수
- 함수는 들어온 입력값을 받아 어떤 처리를 하여 적절한 결괏값을 돌려준다.
입력값 ---> 함수 ----> 결괏값
- 함수의 형태는 입력값과 결괏값의 존재 유무에 따라 4가지 유형으로 나뉜다. 자세히 알아보자.
- 입력값이 있고 결괏값이 있는 함수가 일반적인 함수이다.
def 함수이름(매개변수):
<수행할 문장>
...
return 결과값
- 대부분 위와 같은 구조를 가지고 있다.
def add(a, b):
result = a + b
return result
a = add(3, 4)
print(a)
7
- 일반 함수의 전형적인 예이다. add 함수는 2개의 입력값을 받아서 서로 더한 결괏값을 돌려준다.
- 해당 함수를 사용해서, 입력값으로 3과 4를 주고 결괏값을 돌려받아 볼 수 있다.
결괏값을 받을 변수 = 함수이름(입력인수1, 입력인수2, ...)
- 따라서, 일반적인 함수는 위와 같이 사용할 수 있다.
- 입력값이 없는 함수가 존재할까? 당연히 존재한다.
def say():
return 'Hi'
a = say()
print(a)
Hi
- say라는 이름의 함수를 만들었다. 그런데 매개변수 부분을 나타내는 함수 이름 뒤의 괄호 안이 비어 있다.
- 위 함수를 쓰기 위해서는 say()처럼 괄호 안에 아무 값도 넣지 않아야 한다. 이 함수는 입력값은 없지만 결괏값으로 Hi라는 문자열을 돌려준다. a = say()처럼 작성하면 a에 Hi 문자열이 대입되는 것이다.
결괏값을 받을 변수 = 함수이름()
- 이처럼 입력값이 없고 결괏값만 있는 함수는 위와 같이 사용하면 된다.
- 결괏값이 없는 함수 역시 존재한다.
def add(a, b):
print("%d, %d의 합은 %d입니다." % (a, b, a+b))
- 결괏값이 없는 함수는 호출해도 돌려주는 값이 없기 때문에 다음과 같이 사용한다.
def add(a, b):
print("%d, %d의 합은 %d입니다." % (a, b, a+b))
add(3, 4)
3, 4의 합은 7입니다.
- 즉 결괏값이 없는 함수는 다음과 같이 사용한다.
함수이름(입력인수1, 입력인수2, ...)
- 결괏값이 진짜 없는지 확인하기 위해 다음 예를 직접 입력해 보자.
a = add(3, 4)
3, 4의 합은 7입니다.
-
아마도 여러분은 ‘3, 4의 합은 7입니다.’라는 문장을 출력해 주었는데 왜 결괏값이 없다는 것인지 의아하게 생각할 것이다. 이 부분이 초보자들이 혼란스러워하는 부분이기도 한데 print문은 함수의 구성 요소 중 하나인 <수행할 문장>에 해당하는 부분일 뿐이다. 결괏값은 당연히 없다. 결괏값은 오직 return 명령어로만 돌려받을 수 있다.
-
이를 확인해 보자. 돌려받을 값을 a 변수에 대입하여 출력해 보면 결괏값이 있는지 없는지 알 수 있다.
a = add(3, 4)
print(a)
None
- a 값은 None이다. None이란 거짓을 나타내는 자료형이라고 언급한 적이 있다. add 함수처럼 결괏값이 없을 때 a = add(3, 4)처럼 쓰면 함수 add는 반환 값으로 a 변수에 None을 돌려준다. 이것을 가지고 결괏값이 있다고 생각하면 곤란하다.
- 입력값도 결괏값도 없는 함수 역시 존재한다.
def say():
print('Hi')
- 입력 인수를 받는 매개변수도 없고 return문도 없으니 입력값도 결괏값도 없는 함수이다.
- 이 함수를 사용하는 방법은 단 한 가지이다.
say()
Hi
- 즉, 입력값도 결괏값도 없는 함수는 다음과 같이 사용한다.
함수이름()
- 즉, 결과값이 있는 함수를 사용할 때는(return이 있는 함수) -> 결과값을 받을 변수를 무조건 설정하고 등호(=) 다음에 함수를 호출하게 된다.
- 또한, 결과값이 없는 함수를 사용할 때는(return이 없는 함수) -> 함수만 호출해준다.
- 함수를 호출할 때 매개변수를 지정할 수도 있다.
def add(a, b):
return a+b
- 앞에서 알아본 add 함수이다. 이 함수를 다음과 같이 매개변수를 지정하여 사용할 수 있다.
result = add(a=3, b=7) # a에 3, b에 7을 전달
print(result)
10
- 매개변수를 지정하면 다음과 같이 순서에 상관없이 사용할 수 있다는 장점이 있다.
result = add(b=5, a=3) # b에 5, a에 3을 전달
print(result)
8
- 입력값이 여러 개일 때 그 입력값을 모두 더해 주는 함수를 생각해 보자. 하지만 몇 개가 입력될지 모를 때는 어떻게 해야 할까? 아마도 난감할 것이다. 파이썬은 이런 문제를 해결하기 위해 다음과 같은 방법을 제공한다.
def 함수이름(*매개변수):
<수행할 문장>
...
-
*일반적으로 볼 수 있는 함수 형태에서 괄호 안의 매개변수 부분이 매개변수로 바뀌었다.
-
다음 예를 통해 여러 개의 입력값을 모두 더하는 함수를 직접 만들어 보자. 예를 들어 add_many(1, 2)이면 3을, add_many(1,2,3)이면 6을, add_many(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)이면 55를 돌려주는 함수를 만들어 보자.
def add_many(*args):
result = 0
for i in args:
result += i
return result
- 위에서 만든 add_many 함수는 입력값이 몇 개이든 상관이 없다. **args처럼 매개변수 이름 앞에 을 붙이면 입력값을 전부 모아서 튜플로 만들어 주기 때문이다. 만약 add_many(1, 2, 3)처럼 이 함수를 쓰면 args는 (1, 2, 3)이 되고, add_many(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)처럼 쓰면 args는 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)이 된다. **여기에서 *args는 임의로 정한 변수 이름이다. pey, python처럼 아무 이름이나 써도 된다.
- args는 인수를 뜻하는 영어 단어 arguments의 약자이며 관례적으로 자주 사용한다.
def add_many(*args):
result = 0
for i in args:
result += i
return result
result = add_many(1,2,3)
print(result)
6
- **여러 개의 입력을 처리할 때 def add_many(args)처럼 함수의 매개변수로 args만 사용할 수 있는 것은 아니다.
def add_mul(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
return result
- 위와 같은 함수가 있을 때, add_mul 함수는 여러 개의 입력값을 의미하는 *args 매개변수 앞에 choice 매개변수가 추가되어 있다.
def add_mul(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
return result
result = add_mul("add", 1,2,3,4,5)
print(result)
- 그래서 이렇게 호출해주면 된다.
- 키워드 파라미터를 사용할 때는 매개변수 앞에 별 두 개(**)를 붙인다. 역시 이것도 예제로 알아보자. 먼저 다음과 같은 함수를 작성한다.
def print_kwargs(**kwargs):
print(kwargs)
- print_kwargs 함수는 매개변수 kwargs를 출력하는 함수이다. 이제 이 함수를 다음과 같이 사용해 보자.
def print_kwargs(**kwargs):
print(kwargs)
print_kwargs(a=1)
print_kwargs(name='foo', age=3)
{'a': 1}
{'name': 'foo', 'age': 3}
- 입력값 a=1 또는 name='foo', age=3이 모두 딕셔너리로 만들어져서 출력된다는 것을 확인할 수 있다. 즉 ** kwargs처럼 매개변수 이름 앞에 ** 을 붙이면 매개변수 kwargs는 딕셔너리가 되고 모든 key=value 형태의 결괏값이 그 딕셔너리에 저장된다.
- 여기에서 kwargs는 keyword arguments의 약자이며 args와 마찬가지로 관례적으로 사용한다.
def add_and_mul(a,b):
return a+b, a*b
- 위의 add_and_mul 함수는 2개의 입력 인수를 받아 더한 값과 곱한 값을 돌려주는 함수이다.
def add_and_mul(a,b):
return a+b, a*b
result = add_and_mul(3,4)
print(result)
(7, 12)
-
해당 함수를 호출하면, 결괏값은 a+b와 a*b 2개인데 결괏값을 받아들이는 변수는 result 하나만 쓰였으니 오류가 발생하지 않을까 생각할 수 있다. 하지만 오류는 발생하지 않는다. 그 이유는 함수의 결괏값은 2개가 아니라 언제나 1개라는 데 있다.
-
add_and_mul 함수의 결괏값 a+b와 ab는 튜플값 하나인 (a+b, ab)로 돌려준다.
-
만약 이 하나의 튜플 값을 2개의 결괏값처럼 받고 싶다면 다음과 같이 함수를 호출하면 된다.
def add_and_mul(a,b):
return a+b, a*b
result1, result2 = add_and_mul(3,4)
print(result1)
print(result2)
7
12
- 또한, return문을 2번 사용하면 2개의 결괏값을 돌려주지 않을까라는 생각을 할 수 있다.
def add_and_mul(a,b):
return a+b
return a+b
- 하지만 파이썬에서 위와 같은 함수는 참 어리석은 함수이다.
def add_and_mul(a,b):
return a+b
return a+b
result = add_and_mul(2,3)
print(result)
5
- 이렇게 add_and_mul 함수를 호출해 보면, add_and_mul(2, 3)의 결괏값이 5 하나뿐이다. 즉, 두 번째 return문인 return a*b는 실행되지 않았다는 뜻이다.
- 즉 함수는 return문을 만나는 순간 결괏값을 돌려준 다음 함수를 빠져나가게 된다.
- 특별한 상황일 때 함수를 빠져나가고 싶다면 return을 단독으로 써서 함수를 즉시 빠져나갈 수 있다.
def say_nick(nick):
if nick == "바보":
return
print("나의 별명은 %s 입니다." % nick)
say_nick('야호')
say_nick('바보')
나의 별명은 야호 입니다.
>>>
- 위 함수는 '별명'을 입력으로 전달받아 출력하는 함수이다. 이 함수 역시 반환 값(결괏값)은 없다(문자열을 출력한다는 것과 반환 값이 있다는 것은 전혀 다른 말이다. 혼동하지 말자. 함수의 반환 값은 오로지 return문에 의해서만 생성된다).
- 만약에 입력값으로 '바보'라는 값이 들어오면 return만 사용해서 -> 문자열을 출력하지 않고 함수를 즉시 빠져나간다.
def say_myself(name, old, man=True):
print("나의 이름은 %s 입니다." % name)
print("나이는 %d살입니다." % old)
if man:
print("남자입니다.")
else:
print("여자입니다.")
-
위 함수를 보면 매개변수가 name, old, man=True 이렇게 3개다. 그런데 낯선 것이 나왔다. man=True처럼 매개변수에 미리 값을 넣어 준 것이다. 이것이 바로 함수의 매개변수 초깃값을 설정하는 방법이다. 함수의 매개변수에 들어갈 값이 항상 변하는 것이 아닐 경우에는 이렇게 함수의 초깃값을 미리 설정해 두면 유용하다.
-
중요한 점은, 매개변수로 (name, old, man=True)는 되지만 (name, man=True, old)는 안 된다는 것이다. 초기화시키고 싶은 매개변수를 항상 뒤쪽에 놓는 것을 잊지 말자.
a = 1
def vartest(a):
a = a +1
vartest(a)
print(a)
1
- 다음과 같은 함수가 있고 vartest(a) 이렇게 함수를 호출한다고 했을 때, 결과값은 vartest 함수의 코드 결과인 2가 아니라 1이 나온다.
- 함수 안에서 새로 만든 매개변수는 함수 안에서만 사용하는 "함수만의 변수"이기 때문이다. 즉 def vartest(a)에서 입력값을 전달받는 매개변수 a는 함수 안에서만 사용하는 변수이지 함수 밖의 변수 a가 아니라는 뜻이다.
- 즉 함수 안에서 사용하는 매개변수는 함수 밖의 변수 이름과는 전혀 상관이 없다는 뜻이다.
def vartest(a):
a = a + 1
vartest(3)
print(a)
오류발생
- 위와 같은 코드에서는, print(a)에서 오류가 발생한다.
- vartest(3)을 수행하면 vartest 함수 안에서 a는 4가 되지만 함수를 호출하고 난 뒤에 print(a) 문장은 오류가 발생하게 된다. 그 이유는 print(a)에서 입력받아야 하는 a 변수를 어디에서도 찾을 수가 없기 때문이다.
- 그렇다면 vartest라는 함수를 사용해서 함수 밖의 변수 a를 1만큼 증가시킬 수 있는 방법은 없을까? 이 질문에는 2가지 해결 방법이 있다.
a = 1
def vartest(a):
a = a +1
return a
a = vartest(a)
print(a)
2
- 첫 번째 방법은 return을 사용하는 방법이다. vartest 함수는 입력으로 들어온 값에 1을 더한값을 돌려준다. 따라서 a = vartest(a)라고 대입하면 a가 vartest 함수의 결괏값으로 바뀐다. 여기에서도 물론 vartest 함수 안의 a 매개변수는 함수 밖의 a와는 다른 것이다.
a = 1
def vartest():
global a
a = a+1
vartest()
print(a)
- 두 번째 방법은 global 명령어를 사용하는 방법이다.
- 위 예에서 볼 수 있듯이 vartest 함수 안의 global a 문장은 함수 안에서 함수 밖의 a 변수를 직접 사용하겠다는 뜻이다. 하지만 프로그래밍을 할 때 global 명령어는 사용하지 않는 것이 좋다.
- 왜냐하면 함수는 독립적으로 존재하는 것이 좋기 때문이다. 외부 변수에 종속적인 함수는 그다지 좋은 함수가 아니다. 그러므로 가급적 global 명령어를 사용하는 이 방법은 피하고 첫 번째 방법을 사용하기를 권한다.
- lambda는 함수를 생성할 때 사용하는 예약어로 def와 동일한 역할을 한다.
- 보통 함수를 한줄로 간결하게 만들 때 사용한다. 즉, 함수를 한 줄로 정의할 때 사용한다. 우리말로는 "람다"라고 읽고 def를 사용해야 할 정도로 복잡하지 않거나 def를 사용할 수 없는 곳에 주로 쓰인다.
add = lambda a, b: a+b
result = add(3,4)
print(result)
7
-
위와 같이 lambda를 이용해서 함수를 한 줄로 정의할 수 있다. add는 두 개의 인수를 받아 서로 더한 값을 돌려주는 lambda 함수이다. 위 예제는 def를 사용한 다음 함수와 하는 일이 완전히 동일하다.
-
그리고 lambda 예약어로 만든 함수는 return 명령어가 없어도 결괏값을 돌려준다.
-
lambda의 사용방법은,
lambda 매개변수1, 매개변수2, ... : 매개변수를 이용한 표현식
- 이렇게 표현할 수 있다.
- 지금부터는 좀 더 다양하게 사용자의 입력을 받는 방법과 출력하는 방법을 알아보자.
a = input() # Life is too short, you need python 를 사용자가 입력
print(a)
Life is too short, you need python
- input은 입력되는 모든 것을 문자열로 취급한다.
- 사용자에게 입력받을 때 "숫자를 입력하세요"라든지 "이름을 입력하세요"라는 안내 문구 또는 질문이 나오도록 하고 싶을 때가 있다. 그럴 때는 input()의 괄호 안에 질문을 입력하여 프롬프트를 띄워주면 된다.
number = input("숫자를 입력하세요: ") # 여기서 3이 입력되었다고 가정하면
print(number)
숫자를 입력하세요: 3
3
print("life" "is" "too short") # 1번
print("life"+"is"+"too short") # 2번
lifeistoo short
lifeistoo short
- 위 예에서 ①과 ②는 완전히 동일한 결괏값을 출력한다. 즉 따옴표로 둘러싸인 문자열을 연속해서 쓰면 + 연산을 한 것과 같다.
print("life", "is", "too short")
life is too short
- 콤마(,)를 사용하면 문자열 사이에 띄어쓰기를 할 수 있다.
for i in range(10):
print(i, end=' ')
0 1 2 3 4 5 6 7 8 9
- 03-3에서 for문을 배울 때 만들었던 구구단 프로그램에서 보았듯이 한 줄에 결괏값을 계속 이어서 출력하려면 매개변수 end를 사용해 끝 문자를 지정해야 한다.