일단 하자
# 6. 함수 및 람다(lambda) 본문
함수 정의 및 람다(lambda) 사용
1. 함수 정의 방법
2. 다양한 반환 값
3. *args, **kwargs
4. 중첩함수
5. hint
6. 람다 함수
함수를 왜 사용할까?
반복적이고 중복되는 프로그래밍을 피할 수 있다.
하나의 기능을 수행하는 것을 하나의 함수로 만드는 것이 좋다.
1. 함수 정의 방법
+ 선언
def 함수명(parameter)
code
+ 호출
함수명(parameter)
함수를 호출하는 곳이 함수를 선언하는 곳보다 위에 있으면 에러가 난다. 그러므로 선언 위치가 호출보다 위에 있어야한다.
def hello(world):
print("Hello", world)
hello('Python!')
hello(7777)
def hello_return(world):
val = "Hello" + str(world) # 어떤 타입이 올지 모르므로 str로 변환한다.
return val
str = hello_return("Python!!!!")
print(str)
2. 다양한 반환 값
+ 다중 리턴
def func_mul(x):
y1 = x * 100
y2 = x * 200
y3 = x * 300
return y1, y2, y3
# 3개가 리턴되므로 받는 곳에서도 3개가 받아야한다.
val1, val2, val3 = func_mul(100)
print(val1, val2, val3)
+ 데이터 타입 반환
def func_mul2(x):
y1 = x * 100
y2 = x * 200
y3 = x * 300
return [y1, y2, y3] # ()로 하면 무엇이 반환될까?
lt = func_mul(100)
print(lt, type(lt))
3. *args, **kwargs
def args_func(*args):
print(args)
args_func('Kim')
args_func('Kim', 'Park')
args_func('Kim', 'Park', 'Lee')
가변이다. 매개변수가 몇개가 넘어가는지 모를 때, 또는 매개변수가 넘어오는 것에 따라서 함수의 작동을 달리할 때 사용한다. 다양한 매개변수 형태를 받아서 함수의 형태가 바뀌는 동작을 시행한다. 받은 인자를 튜플로 넘겨준다. 튜플이라는 것은 iterate를 할 수 있다는 것이다.
def kwargs_func(**kwargs):
print(kwargs)
kwargs_func(name1 = 'kim', name2 = 'park', name3 = 'Lee') # 물론 가변이다.
*가 하나일 때는 튜플로 받고, ** 두개일 때는 딕셔너리로 받는다. 물론 딕셔너리로 받기 때문에 iterate가 가능하다.
def kwargs_func2(**kwargs):
for k, v in kwargs.items():
print(k, v)
kwargs_func2(name1 = 'kim', name2 = 'park', name3 = 'Lee')
+ enumerate
index를 만들어준다.
def args_func2(*args):
for index, value in enumerate(args): # enumerate(range(10))을 하면 index도 만들어지고 숫자도 만들어진다.
print(index, value)
args_func2('Kim', 'Park', 'Lee')
+ 전체 혼합
def example_mul(arg1, arg2, *args, **kwargs):
print(arg1, arg2, args, kwargs)
example_mul(10, 20) # 뒤에 2개는 가변인자이므로 안 넘겨줘도 된다.
exmple_mul(10, 20, 'park', 'kim')
exmple_mul(10, 20, 'park', 'kim', age1=24, age2=35)
# 매우 중요하다ㅏㅏㅏㅏㅏㅏㅏㅏ
arg1과 arg2는 반드시 넘겨줘야하고, *args와 **kwargs는 가변적으로 받는다. 이러한 기능은 기능을 함축해서 코딩을 할 수 있도록 한다.
4. 중첩 함수
참고. 파이썬 데코레이터 클로저
def nested_func(num):
def func_in_func(num): # 함수를 선언한 것이지 호출 된 것은 아니다.
print('>>>', num)
print("in func")
func_in_func(num + 10000)
nested_func(10000)
그렇다면 함수 바깥에서 함수 안에 있는 함수인 func_in_func을 호출하면 어떻게 될까?
func_in_func(10000)
아마도 func_in_func 함수객체의 scope는 nested_func안에서만 정의되는 것 같다.
5. hint
파라미터의 타입과 반환 타입을 명시해주는 것. (예외를 발생시키지는 않는다.)
def func_mul3(x : int) -> list:
y1 = x * 100
y2 = x * 200
y3 = x * 300
return [y1, y2, y3]
print(func_mul3(5))
6. 람다(lambda)
메모리 절약, 코드 간결, 가독성 향상(너무 많이 사용할 경우 오히려 가독성이 떨어질 수 있다.)
함수는 객체를 생성하고 그로 인해 리소스(메모리)가 할당된다. 그러나 람다는 즉시 실행되며 heap을 초기화. 즉, 메모리를 초기화한다.
일반적인 함수는 객체를 생성하기 때문에 변수에 할당이 가능하다.
def mul_10(num : int) -> int:
return num * 10
var_func = mul_10
print(var_func)
print(type(var_func))
print(var_func(10))
type의 출력결과를 보면 'function'이라는 타입으로 객체가 생성된 것을 볼 수 있다. 그말은, 리소스가 할당되었다. 함수는 호출되지 않았지만 'at 0x0000024401E54318' 이라고 저 메모리에 올라가 있다. 그래서 생성된 함수 객체를 var_func변수에 대입한 것이다.
람다식은 주로 익명함수를 사용할 때 많이 쓴다.
lambda_mul_10 = lambda x : x * 10
print('lambda >>>', lambda_mul_10(10))
x는 parameter이고, 반환값이 x * 10이다.
매개변수로 함수를 받을 수 있다. 여기서 람다가 빛을 발한다.
def func_final(x, y, func):
print(x * y * func(10))
func_final(10, 10, lambda x : x * 1000)
# 이런식으로 바로 람다식을 사용해서 함수를 넘겨줄 수 있다.
함수를 매개변수로 넘길 때 자주 사용한다. 한번 실행하는 경우에는 바로 함수를 람다식으로 작성해서 넘기면 메모리를 절약할 수 있다.
'파이썬 웹 개발 > 파이썬 기초 개념' 카테고리의 다른 글
# 7 - 2. 클래스 상속 및 다중 상속 (0) | 2019.11.26 |
---|---|
# 7 - 1. 클래스 선언 및 self의 이해 (0) | 2019.11.14 |
# 5 - 3. 조건문, 반복문 퀴즈 (0) | 2019.11.13 |
# 5 - 2. 반복문 (0) | 2019.11.13 |
# 5 - 1. 조건문 (0) | 2019.11.13 |