728x90
반응형

참고자료:https://wikidocs.net/24

 

04-1 함수

`[동영상 강의]` : [점프 투 파이썬 04-1 함수](https://www.youtube.com/watch?v=d4NBeJzxwKQ&list=PLGSQkvB9T6rvnDop8…

wikidocs.net

 

# 함수

# 함수란 무엇인가?
# 입력값을 가지고 어떤 일을 수행한 후 그 결과물을 내어 놓는 것이 바로 함수가 하는 일이다.

# 함수를 사용하는 이유?
# 반복되는 부분이 있을 경우, ‘반복적으로 사용되는 가치 있는 부분’을 한 뭉치로 묶어 ‘어떤 입력값을 주었을 때 어떤 결괏값을 리턴해 준다’라는 식의 함수로 작성하는 것이다.

# 함수를 사용하는 또 다른 이유는 자신이 작성한 프로그램을 기능 단위의 함수로 분리해 놓으면 프로그램 흐름을 일목요연하게 볼 수 있기 때문이다. 프로그램에서도 입력한 값이 여러 함수를 거치면서 원하는 결괏값을 내는 것을 볼 수 있다. 이렇게 되면 프로그램 흐름도 잘 파악할 수 있고 오류가 어디에서 나는지도 쉽게 알아차릴 수 있다.

# 파이썬 함수의 구조

def 함수_이름(매개변수):
    수행할_문장1
    수행할_문장2
    ...


def add(a, b): 
    return a + b


# 이 함수의 이름은 add이고 입력으로 2개의 값을 받으며 리턴값(출력값)은 2개의 입력값을 더한 값이다.

a = 3
b = 4
c = add(a, b)  # add(3, 4)의 리턴값을 c에 대입
print(c)
7


# 매개변수와 인수
# 매개변수(parameter)와 인수(arguments)는 혼용해서 사용하는 용어이므로 잘 기억해 두자. 매개변수는 함수에 입력으로 전달된 값을 받는 변수, 인수는 함수를 호출할 때 전달하는 입력값을 의미한다.

def add(a, b):  # a, b는 매개변수
    return a+b

print(add(3, 4))  # 3, 4는 인수

# 입력값을 다른 말로 함수의 인수, 파라미터, 매개변수 등으로 말하기도 하고, 함수의 리턴값을 결괏값, 출력값, 반환값, 돌려 주는 값 등으로 말하기도 한다. 




# 입력값과 리턴값에 따른 함수의 형태


# 일반적인 함수

def 함수_이름(매개변수):
    수행할_문장
    ...
    return 리턴값


def add(a, b): 
    result = a + b 
    return result

a = add(3, 4)
print(a)
7

리턴값을_받을_변수 = 함수_이름(입력_인수1, 입력_인수2, ...)



# 입력값이 없는 함수

def say(): 
    return 'Hi' 

a = say()
print(a)
# Hi

# 위 함수를 쓰기 위해서는 say()처럼 괄호 안에 아무런 값도 넣지 않아야 한다. 이 함수는 입력값은 없지만, 리턴값으로 "Hi"라는 문자열을 리턴한다. 즉, a = say()처럼 작성하면 a에 "Hi"라는 문자열이 대입되는 것이다.

리턴값을_받을_변수 = 함수_이름()



# 리턴값이 없는 함수


def add(a, b): 
    print("%d, %d의 합은 %d입니다." % (a, b, a+b))

add(3, 4)
# 3, 4의 합은 7입니다.


함수_이름(입력_인수1, 입력_인수2, ...)


# 리턴값은 오직 return 명령어로만 돌려받을 수 있다.

a = add(3, 4)
# 3, 4의 합은 7입니다.
print(a)
None

# a 값으로 None이 출력되었다. None이란 ‘거짓을 나타내는 자료형’이라고 언급한 적이 있다. None을 리턴한다는 것은 리턴값이 없다는 것이다.



# 입력값도, 리턴값도 없는 함수


def say(): 
    print('Hi')

say()
# Hi




# 매개변수를 지정하여 호출하기

# 함수를 호출할 때 매개변수를 지정할 수도 있다.
def sub(a, b):
    return a - b


result = sub(a=7, b=3)  # a에 7, b에 3을 전달
print(result)
4

# 매개변수를 지정하면 다음과 같이 순서에 상관없이 사용할 수 있다는 장점이 있다.

result = sub(b=5, a=3)  # b에 5, a에 3을 전달
print(result)
-2


# 입력값이 몇 개가 될지 모를 때는 어떻게 해야 할까?


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 = result + i   # *args에 입력받은 모든 값을 더한다.
    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처럼 아무 이름이나 써도 된다.

result = add_many(1,2,3)
print(result)
6
result = add_many(1,2,3,4,5,6,7,8,9,10)
print(result)
55


# 여러 개의 입력을 처리할 때 def add_many(*args)처럼 함수의 매개변수로 *args 하나만 사용할 수 있는 것은 아니다. 다음 예를 살펴보자.

def add_mul(choice, *args): 
    if choice == "add":   # 매개변수 choice에 "add"를 입력받았을 때
        result = 0 
        for i in args: 
            result = result + i 
    elif choice == "mul":   # 매개변수 choice에 "mul"을 입력받았을 때
        result = 1 
        for i in args: 
            result = result * i 
    return result 


result = add_mul('add', 1,2,3,4,5)
print(result)
15
result = add_mul('mul', 1,2,3,4,5)
print(result)
120



# 키워드 매개변수, kwargs

# 이번에는 키워드 매개변수에 대해 알아보자. 키워드 매개변수를 사용할 때는 매개변수 앞에 별 2개(**)를 붙인다. 역시 이것도 예제로 알아보자. 먼저 다음과 같은 함수를 작성해 보자.

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

print_kwargs(a=1)
{'a': 1}
print_kwargs(name='foo', age=3)
{'age': 3, 'name': 'foo'}

# 함수의 입력값으로 a=1이 사용되면 kwargs는 {'a': 1}이라는 딕셔너리가 되고 입력값으로 name='foo', age=3이 사용되면 kwargs는 {'age': 3, 'name': 'foo'}라는 딕셔너리가 된다. 즉, **kwargs처럼 매개변수 이름 앞에 **을 붙이면 매개변수 kwargs는 딕셔너리가 되고 모든 Key=Value 형태의 입력값이 그 딕셔너리에 저장된다는 것을 알 수 있다.


# 함수의 리턴값은 언제나 하나이다

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

result = add_and_mul(3,4)

# 리턴값은 a+b와 a*b인데, 리턴값을 받아들이는 변수는 result 하나만 쓰였으므로 오류가 발생하지 않을까? 당연한 의문이다. 하지만 오류는 발생하지 않는다. 그 이유는 함수의 리턴값은 2개가 아니라 언제나 1개라는 데 있다. add_and_mul 함수의 리턴값 a+b와 a*b는 튜플값 하나인 (a+b, a*b)로 리턴된다.

result = (7, 12)

# 만약 이 하나의 튜플 값을 2개의 값으로 분리하여 받고 싶다면 함수를 다음과 같이 호출하면 된다.

result1, result2 = add_and_mul(3, 4)

result1, result2 = (7, 12)
result1 = 7
result2 = 12

# return 문을 2번 사용하면 2개의 리턴값을 돌려 주지 않을까? 

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

result = add_and_mul(2, 3)
print(result)
5

# add_and_mul(2, 3)의 리턴값은 5 하나뿐이다. 두 번째 return 문인 return a * b는 실행되지 않았다는 뜻이다. 즉, 함수는 return 문을 만나는 순간, 리턴값을 돌려 준 다음 함수를 빠져나가게 된다.

# 이 함수는 다음과 완전히 동일하다.
def add_and_mul(a,b): 
    return a+b 

# 즉 함수는 return문을 만나는 순간 결괏값을 돌려준 다음 함수를 빠져나가게 된다.

 

 

 


# return의 또 다른 쓰임새

def say_nick(nick): 
    if nick == "바보": 
        return 
    print("나의 별명은 %s 입니다." % nick)
# 위는 매개변수 nick으로 별명을 입력받아 출력하는 함수이다. 이 함수 역시 리턴값은 없다. 이때 문자열을 출력한다는 것과 리턴값이 있다는 것은 전혀 다른 말이므로 혼동하지 말자. 함수의 리턴값은 오로지 return 문에 의해서만 생성된다.
    
# 만약 입력값으로 '바보'라는 값이 들어오면 문자열을 출력하지 않고 함수를 즉시 빠져나간다.




# 매개변수에 초깃값 미리 설정하기
# 매개변수에 초깃값을 미리 설정해 주는 경우이다.
    
# default1.py
def say_myself(name, age, man=True): 
    print("나의 이름은 %s 입니다." % name) 
    print("나이는 %d살입니다." % age) 
    if man: 
        print("남자입니다.")
    else: 
        print("여자입니다.")

# 위 함수를 보면 매개변수가 name, age, man=True이다. 그런데 낯선 것이 나왔다. man=True처럼 매개변수에 미리 값을 넣어 준 것이다. 이것이 바로 함수의 매개변수에 초깃값을 설정하는 방법이다.
        
say_myself("박응용", 27)
say_myself("박응용", 27, True)
'''
나의 이름은 박응용입니다.
나이는 27살입니다.
남자입니다.
'''

say_myself("박응선", 27, False)
'''
나의 이름은 박응선입니다.
나이는 27살입니다.
여자입니다.
'''

# 함수의 매개변수에 초깃값을 설정할 때 주의할 것

'''
# default2.py
def say_myself(name, man=True, age): 
    print("나의 이름은 %s 입니다." % name) 
    print("나이는 %d살입니다." % age) 
    if man: 
        print("남자입니다.") 
    else: 
        print("여자입니다.")
'''

# 바뀐 부분은 초깃값을 설정한 매개변수의 위치
# 초기화하고 싶은 매개변수는 항상 뒤쪽에 놓아야 한다는 것을 잊지 말자.




# 함수 안에서 선언한 변수의 효력 범위

# vartest.py
a = 1 # 전역변수
def vartest(a):
    a = a +1 # 지역변수

vartest(a)
print(a)

#  함수 안에서 사용하는 매개변수는 함수 안에서만 사용하는 ‘함수만의 변수’이기 때문이다. 즉, def vartest(a)에서 입력값을 전달받는 매개변수 a는 함수 안에서만 사용하는 변수일 뿐, 함수 밖의 변수 a와는 전혀 상관없다는 뜻이다.

# vartest_error.py
def vartest(a):
    a = a + 1

vartest(3)
print(a)

# 함수 안에서 선언한 매개변수는 함수 안에서만 사용될 뿐, 함수 밖에서는 사용되지 않는다.



# 함수 안에서 함수 밖의 변수를 변경하는 방법

# 1. return 사용하기

# vartest_return.py
a = 1 
def vartest(a): 
    a = a +1 
    return a

a = vartest(a) 
print(a)

# 첫 번째 방법은 return을 사용하는 방법이다. vartest 함수는 입력으로 들어온 값에 1을 더한 값을 리턴하도록 변경했다. 따라서 a = vartest(a)라고 작성하면 a에는 vartest 함수의 리턴값이 대입된다.

# 여기에서도 물론 vartest 함수 안의 a 매개변수는 함수 밖의 a와는 다른 것이다.


# 2. global 명령어 사용하기

# vartest_global.py
a = 1 
def vartest(): 
    global a 
    a = a+1

vartest() 
print(a)

# 두 번째 방법은 global 명령어를 사용하는 방법이다. 위 예에서 볼 수 있듯이 vartest 함수 안의 global a 문장은 함수 안에서 함수 밖의 a 변수를 직접 사용하겠다는 뜻이다. 하지만 프로그래밍을 할 때 global 명령어는 사용하지 않는 것이 좋다. 함수는 독립적으로 존재하는 것이 좋기 때문이다. 외부 변수에 종속적인 함수는 그다지 좋은 함수가 아니다. 따라서 되도록 global 명령어를 사용하는 이 방법은 피하고 첫 번째 방법을 사용하기를 권한다.



a = [1,2,3,4]
print(a.append(5))
None
# def append(num):
#     # 리스트에 하나를 추가함
#     return None

a = [1,2,3,4]
result = a.append(5)
print(result)
None
print(a)
[1,2,3,4,5]


a = [1,2,3,4]
result = a.insert(0,10)
print(result)
None
print(a)
[10,1,2,3,4]


a = [1,2,3,4]
result = a.pop()
# return 값이 있음. return 4
print(result)
4
print(a)
[1,2,3]





# lambda 예약어
# lambda는 함수를 생성할 때 사용하는 예약어로, def와 동일한 역할을 한다. 보통 함수를 한 줄로 간결하게 만들 때 사용한다. 우리말로는 ‘람다’라고 읽고 def를 사용해야 할 정도로 복잡하지 않거나 def를 사용할 수 없는 곳에 주로 쓰인다.

함수_이름 = lambda 매개변수1, 매개변수2, ... : 매개변수를_이용한_표현식


add = lambda a, b: a+b
result = add(3, 4)
print(result)
7

# lambda로 만든 함수는 return 명령어가 없어도 표현식의 결괏값을 리턴한다.

# add는 2개의 인수를 받아 서로 더한 값을 리턴하는 lambda 함수이다. 위 예제는 def를 사용한 다음 함수와 하는 일이 완전히 동일하다.

def add(a, b):
    return a+b

result = add(3, 4)
print(result)
7


a = [lambda a, b: a+b, lambda a, b: a*b]
print(a[0](3,4))
7
print(a[1](3,4))
12






반응형

+ Recent posts