본문 바로가기
코딩 연습/코딩배우기

[python] 패킹(packing), 언패킹(unpacking) 그리고 가변인자

by good4me 2020. 8. 23.

goodthings4me.tistory.com

 

■ 패킹은 하나 이상의 값들을 묶는 행위이고, 언패킹은 묶여 있는 값들을 풀어내는 행위임

tpl = (1, 3, 4, 6) # 패킹
lst = [10, 20, 30, 40] # 패킹

a, b, c, d = tpl # 언패킹
print(a, b, c, d) # 1 3 4 6

x, y, *z = tpl  # 언패킹
print(x, y, *z) # 1 3 4 6
print(x, y, z) # 1 3 [4, 6] - z는 리스트로 묶임


n, m, *others = lst  # 언패킹
print(n, m, *others) # 10 20 30 40
print(n, m, others) # 10 20 [30, 40]


def nums():
    return 1, 2, 3, 4, 5  # 파이썬은 여러 개의 리턴 값 가능(튜플 패킹, 소괄호 생략)

p, q, r, s, t = nums() # 언패킹
print(p, q, r, s, t)  # 1 2 3 4 5

tt, *oth = nums() # 언패킹
print(tt, *oth)  # 1 2 3 4 5
print(tt, oth)  # 1 [2, 3, 4, 5]

 

■ 가변인자(Variable parameter) - *변수,  **변수 

# func(*iterable), func(**dict) : 함수 호출 시 언패킹으로 전달됨

def show_person(name, age, height):
    print(name, age, height, sep=', ')

p = ('Choi', 24, 180)
show_person(*p)  # Choi, 24, 180
#show_person(p) - TypeError : arguments 수 부족

pl = ['Park', 24, 180]
show_person(*pl) # Park, 24, 180 - 리스트도 언패킹 되어 전달


def show_nums(n, m, *other):
    print(n, m, other, sep=', ')

show_nums(1, 2, 3, 4, 5)  # 1, 2, (3, 4, 5) - 3번째 이후 값은 튜플로 other에 전달


def who(a, b, c):
    print(a, b, c, sep=', ')

who(*[11, 22, 33,]) # 11, 22, 33 -  리스트
who(*(10, 20, 30)) # 10, 20, 30 - 튜플
who(*'god') # g, o, d - 문자열


# func(**dict) 예)

d = dict(a = 10, b = 20, c = 30)  # {'a': 10, 'b': 20, 'c': 30}
who(*d)  # a, b, c  -  키(key)가 매개변수에 전달
who(**d)  # 10, 20, 30  - 값이 매개변수에 전달 (key가 한 문자인 경우)

dd = dict(aa = 10, bb = 20, cc = 30)  # {'aa': 10, 'bb': 20, 'cc': 30}
who(*dd)  # aa, bb, cc
#who(**dd)  # TypeError: who() got an unexpected keyword argument 'aa'

dic = {'apple': 20, 'banana': 15, 'orange': 30}
who(*dic)  # apple, banana, orange
#who(**dic)  # TypeError: who() got an unexpected keyword argument 'apple'
who(*dic.keys())  # apple, banana, orange
who(*dic.values())  # 20, 15, 30
who(*dic.items())  # ('apple', 20), ('banana', 15), ('orange', 30)

good4me.co.kr

 

■ 함수 정의(선언) 시 매개변수 *args는 전달된 객체를 튜플로 묶어(패킹) 변수에 저장

def whos(*args):
    print('type(args):', type(args), args)

whos({})  # type(args): <class 'tuple'> ({},)
whos([])  # type(args): <class 'tuple'> ([],)
whos(())  # type(args): <class 'tuple'> ((),)
whos(1)  # type(args): <class 'tuple'> (1,)
whos(44, 55, 66, 77)  # type(args): <class 'tuple'> (44, 55, 66, 77)
whos(*[44, 55, 66])  # type(args): <class 'tuple'> (44, 55, 66)

ts = 45, 43, 46
whos(ts)  # type(args): <class 'tuple'> ((45, 43, 46),)

ls = [47, 27]
whos(ls)  # type(args): <class 'tuple'> ([47, 27],)

 

■ 함수 정의(선언) 시 매개변수 **args는 딕셔너리의 생성으로 이어지며, 딕셔너리(key=value)의 형태로 전달해야 함

def func(**args):  # 보통 **kwargs로 표시
    print(type(args), args)

func(f = 10)  # <class 'dict'> {'f': 10}  - {'f': 10} 생성되어 args에 전달
func(a = 20, b = 30)  # <class 'dict'> {'a': 20, 'b': 30}
func(f = 100, g = 200)  # <class 'dict'> {'f': 100, 'g': 200}

#func(dic)  # TypeError: func() takes 0 positional arguments but 1 was given
#func({'f': 100, 'g': 200})  # TypeError: func() takes 0 positional ~
#func(*dic)  # func() takes 0 positional arguments but 3 were given
#func(*{'f': 100, 'g': 200})  # func() takes 0 positional arguments but 2 ~
# 각 인자를 positional arguments 로 인식, **args 형태가 아니라서 에러 발생

func(**dic)  # <class 'dict'> {'apple': 20, 'banana': 15, 'orange': 30}
func(**{'f': 100, 'g': 200})  # <class 'dict'> {'f': 100, 'g': 200}

 

■ *args **kwargs에 값 동시 전달

def com_func(n, *args, **kwargs):
    print(f'type(n) : {type(n)}')  # type(n) : <class 'int'>
    print(f'type(agrs) : {type(args)}')  # type(agrs) : <class 'tuple'>
    print(f'type(kwargs) : {type(kwargs)}')  # type(kwargs) : <class 'dict'>
    return print(n, args, kwargs)

com_func(10, 20, name = 'Park')  # 10 (20,) {'name': 'Park'}

 

[참고 자료] 윤성우의 열혈 파이썬 중급편

 

댓글