All Articles

파이썬 기억 더듬기 (4) - 파이썬 함수식 및 람다

다중 리턴 함수

함수 하나에서 값 여러 개 리턴받기

def mul_return(x):
  y1 = x * 10
  y2 = x * 100
  y3 = x * 1000

  return y1, y2, y3
val1, val2, val3 = mul_return(10)
print(val1, val2, val3)
100 1000 10000

이때 리턴하는 값은 정수형 데이터다.

리턴하는 값 수만큼 변수를 지정하지 않으면 튜플 형태로 리턴한다.

val = mul_return(10)
print(val)
(100, 1000, 10000)

리턴 자료형을 지정할 수도 있다.

def mul_return_list(x):
  y1 = x * 10
  y2 = x * 100
  y3 = x * 1000

  return [y1, y2, y3]
mul_return_list(10)
[100, 1000, 10000]

가변인자

함수가 받는 인자 수가 고정되지 않았을 때 사용한다.

가변인자 형태를 어떻게 지정하느냐에 따라 받을 수 있는 매개변수 형태가 달라진다.

*args

def args_func(*args):
  print(args)

  for i in args:
    print(i)

인자를 하나(‘apple’)만 전달할 수도 있고

args_func('apple')
('apple',)  # print(args)
apple  # for문 내부 print(i)

두 개 이상을 전달할 수도 있다.

args_func('pineapple', 'watermelon', 'kiwi')
('pineapple', 'watermelon', 'kiwi')
pineapple
watermelon
kiwi

enumerate() 함수를 이용하면 다중 리턴값에 인덱스 번호를 매겨 활용할 수 있다.

def args_enumerate_func(*args):
  for idx, value in enumerate(args):
    print(idx, value)
args_func('banana', 'kiwi')
0 banana
1 kiwi

**kwargs

딕셔너리 자료형도 인자로 받을 수 있다.

def kwargs_func(**kwargs):
  print(kwargs)

  for key, value in kwargs.items():
    print(key, value)
kwargs_func(name1='A')
{'name1': 'A'}  # print(kwargs)
name1 A  # for 문 내부 print(key, value)
kwargs_func(name1='A', name2='B', name3='C')
{'name1': 'A', 'name2': 'B'}
name1 A
name2 B

만약 *args를 인자로 받는 함수에 딕셔너리 자료형을 인자로 넘기거나, **kwargs를 인자로 받는 함수에 단일 값을 인자로 넘긴다면 TypeError가 발생한다.

args_func(fruit1='apple')
TypeError: args_func() got an unexpected keyword argument 'fruit1'
kwargs_func('A')
TypeError: kwargs_func() takes 0 positional arguments but 1 was given

*args, **kwargs를 모두 인자로 받는 함수

단 순서는 반드시 단일 인자 다음에 *args, 그 다음에 **kwargs를 둬야 한다.

def args_kwargs_func(arg1, arg2, *args, **kwargs):
  print(arg1, arg2, args, kwargs)
args_kwargs_func(1, 2, 'Kang', 'Cha', age1=20, age2=24)
1 2 ('Kang', 'Cha'), {'age1': 20, 'age2': 24}

중첩함수 (클로저)

def nested_func(num):
  def func_in_func(num):
    print(num)
  print('in func')
  func_in_func(num + 10000)
nested_func(10000)
in func
20000

리턴 순서를 보면 func_in_func 함수 안에 있는 print문은 건너뛴 것을 알 수 있다.

def nested_func(num):
  def func_in_func(num):
    print(num)  # 3. 마지막에 실행
  print('in func')  # 1. 가장 먼저 실행
  func_in_func(num + 10000)  # 2. 그 다음 실행

nested_func 함수 호출 후 func_in_func에서 바로 인자를 넘겨받지만 실제 func_in_func 함수 실행은 nested_func 내 다른 코드를 순차로 실행하면서 실행된다.

함수에 힌트 주기

def mul3(x: int) -> list:
  y1 = x * 10
  y2 = x * 100
  y3 = x * 1000

  return [y1, y2, y3]

라는 것은 int형 인자를 넘겨야하고, 리턴값 형태는 list라는 뜻이다. 힌트를 줘서 좀 더 친절한 코드로 만들 수 있다.

lambda

람다식을 사용하면 메모리를 절약할 수 있고, 가독성 높은 간결한 코드를 작성할 수 있다. 하지만 남용하면 오히려 가독성이 떨어지니 필요한 곳에만 사용해야 한다.

일반 함수 vs. 람다식

  • 일반 함수: 객체 생성 -> 리소스(메모리) 할당
  • 람다식: 즉시 실행(Heap 초기화) -> 메모리 초기화

일반 함수를 선언해보자.

def mul_10(x):
  return x * 10
mul_10_func = mul_10
print(mul_10_func)
<function mul_10 at 0x7f81e002c940>

함수를 선언하니 객체가 생성되었다. 객체가 생성되었다는 것은 메모리가 할당되었다는 뜻이다.

람다식 사용법

lambda_mul_10 = lambda x: x * 10
print(lambda_mul_10(10))
100

함수를 인자로 받는 함수를 만들어서 람다식을 인자로 넘겨줄 수도 있다.

def lambda_ex(x, y, func):
  print(x * y * func(10))
lambda_ex(10, 10, lambda_mul_10)
10000  # 10 * 10 * (10*10)

혹은 람다식을 바로 만들어서 넘길 수 있다.

lambda_ex(10, 10, lambda x: x * 100)
100000  # 10 * 10 * (100 * 10)