일단 하자

# 6. 함수 및 람다(lambda) 본문

파이썬 웹 개발/파이썬 기초 개념

# 6. 함수 및 람다(lambda)

coredump064 2019. 11. 13. 19:41

함수 정의 및 람다(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) 
# 이런식으로 바로 람다식을 사용해서 함수를 넘겨줄 수 있다.

 함수를 매개변수로 넘길 때 자주 사용한다. 한번 실행하는 경우에는 바로 함수를 람다식으로 작성해서 넘기면 메모리를 절약할 수 있다.

Comments