Skip to content

Latest commit

 

History

History
611 lines (407 loc) · 19.1 KB

점프 투 파이썬 정리(함수, 사용자 입력과 출력).md

File metadata and controls

611 lines (407 loc) · 19.1 KB

점프 투 파이썬 정리(함수, 사용자 입력과 출력)

함수란

  • 입력값을 가지고 어떤 일을 수행한 다음에 그 결과물을 내어놓는 것, 이것이 바로 함수가 하는 일이다.
  • 반복되는 부분이 있을 경우 "반복적으로 사용되는 가치 있는 부분"을 한 뭉치로 묶어서 "어떤 입력값을 주었을 때 어떤 결괏값을 돌려준다"라는 식의 함수로 작성하는 것이 현명하다.

Python 함수의 구조

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)
  • 그래서 이렇게 호출해주면 된다.

키워드 파라미터 kwargs

  • 키워드 파라미터를 사용할 때는 매개변수 앞에 별 두 개(**)를 붙인다. 역시 이것도 예제로 알아보자. 먼저 다음과 같은 함수를 작성한다.
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의 또 다른 쓰임새

  • 특별한 상황일 때 함수를 빠져나가고 싶다면 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

  • 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, ... : 매개변수를 이용한 표현식
  • 이렇게 표현할 수 있다.

사용자 입력과 출력

  • 지금부터는 좀 더 다양하게 사용자의 입력을 받는 방법과 출력하는 방법을 알아보자.

input의 사용

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 함수 자세히 알기

큰따옴표(")로 둘러싸인 문자열은 + 연산과 동일하다

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를 사용해 끝 문자를 지정해야 한다.