Skip to content

19. 위치 인수(Positional Argument)와 키워드 인수(Keyword Argument)


1. 키워드

  • 위치 인수(Positional Argument)와 리스트(튜플) 언패킹
  • 키워드 인수(Keyword Argument)와 딕셔너리 언패킹
  • 가변 인수(Variable Argument)


2. 위치 인수와 키워드 인수

  • 이번에는 함수에서 위치 인수, 키워드 인수를 사용하는 방법과 리스트, 딕셔너리 언패킹을 활용하는 방법을 알아보자.


3. 위치 인수와 리스트 언패킹 사용하기

  • 다음과 같이 함수에 인수를 순서대로 넣는 방식을 위치 인수라고 한다.


>>> print(10, 20, 30)
10 20 30


  • print10, 20, 30 순으로 넣었으므로 출력될 때도 10 20 30으로 출력된다.


1) 위치 인수를 사용하는 함수를 만들고 호출하기

  • 숫자 세 개를 각 줄에 출력하는 함수를 만들어보자.


>>> def print_numbers(a, b, c):
...     print(a)
...     print(b)
...     print(c)
...


  • print_numbers에 숫자 세 개를 넣으면 각 줄에 숫자가 출력된다.


>>> print_numbers(10, 20, 30)
10
20
30


2) 언패킹 사용하기

  • 이렇게 인수를 순서대로 넣을 때는 리스트나 튜플을 사용할 수도 있다.


  • 다음과 같이 리스트 또는 튜플 앞에 *(애스터리스크)를 붙여서 함수에 넣어주면 된다.


함수(*리스트)
함수(*튜플)
>>> x = [10, 20, 30]

>>> print_numbers(*x)
10
20
30


  • print_numbers10, 20, 30이 들어있는 리스트 x를 넣고 *만 붙였는데도 숫자가 각 줄에 출력되었다.
  • 즉, 리스트(튜플) 앞에 *를 붙이면 언패킹이 되어서 print_numbers(10, 20, 30)과 똑같은 동작이 된다.


001


  • 리스트 변수 대신 리스트 앞에 바로 *를 붙여도 동작은 같다.


>>> print_numbers(*[10, 20, 30])
10
20
30


  • 단, 이때 함수의 매개변수 개수와 리스트의 요소 개수는 같아야 한다.


3) 가변 인수 함수 만들기

  • 위치 인수와 리스트 언패킹은 인수의 개수가 정해지지 않은 가변 인수에 사용한다.
  • 즉, 같은 함수에 인수 한 개를 넣을 수도 있고, 열 개를 넣을 수도 있으며, 또는 인수를 넣지 않을 수도 있다.


  • 다음과 같이 가변 인수 함수는 매개변수 앞에 *를 붙여서 만든다.


def 함수이름(*매개변수):
    코드


  • 다음과 같이 함수를 만들 때 괄호 안에 *args와 같이 매개변수 앞에 *를 붙인다.


>>> def print_numbers(*args):
...     for arg in args:
...         print(arg)
...


  • print_numbers 함수에 숫자를 넣어서 호출해 보자.


>>> print_numbers(10)
10
>>> print_numbers(10, 20, 30, 40)
10
20
30
40


  • 이렇게 함수 인수 여러 개를 직접 넣어도 되고, 리스트(튜플) 언패킹을 사용해도 된다.


>>> x = [10]
>>> print_numbers(*x)
10

>>> y = [10, 20, 30, 40]
>>> print_numbers(*y)
10
20
30
40


  • 이처럼 함수를 만들 때 def print_numbers(*args):와 같이 매개변수에 *를 붙여주면 가변 인수 함수를 만들 수 있다.
  • 그리고 이런 함수를 호출할 때는 인수를 각각 넣거나, 리스트(튜플) 언패킹을 사용하면 된다.


고정 인수와 가변 인수를 함께 사용하기

  • 고정 인수와 가변 인수를 함께 사용할 때는 다음과 같이 고정 매개변수를 먼저 지정하고 나서 매개변수에 *를 붙여주면 된다.


>>> def print_numbers(a, *args):
...     print(a)
...     print(args)
...

>>> print_numbers(1)
1
()
>>> print_numbers(1, 10, 20)
1
(10, 20)
>>> print_numbers(*[10, 20, 30])
10
(20, 30)


  • 단, 이때 def print_numbers(*args, a):처럼 *args가 고정 매개변수보다 앞쪽에 오면 안 된다.
  • 매개변수 순서에서 *args는 반드시 가장 뒤쪽에 와야 한다.


4. 키워드 인수 사용하기

  • 지금까지 함수에 인수를 넣을 때 값이나 변수를 그대로 넣었다.
  • 그러다 보니 각각의 인수가 무슨 용도인지 알기가 어려웠다.


  • 예를 들어 개인 정보를 출력하는 함수를 만들어보자.


>>> def personal_info(name, age, address):
...     print("이름: ", name)
...     print("나이: ", age)
...     print("주소: ", address)
...


  • 이 함수를 사용할 때는 첫 번째 인수에 name, 두 번째 인수에 age, 세 번째 인수에 address를 넣어야 한다.
  • 만약 인수의 순서가 달라지면 잘못된 결과가 출력될 것이다.
  • 이처럼 위치 인수의 경우 인수의 순서와 용도를 모두 기억해야 해서 불편하다.
  • 그래서 파이썬에서는 인수의 순서와 용도를 매번 기억하지 않도록 키워드 인수라는 기능을 제공한다.


  • 키워드 인수는 말 그대로 인수에 이름(키워드)를 붙이는 기능인데 다음과 같이 키워드=값 형식으로 사용한다.


함수(키워드=)


  • personal_info 함수를 키워드 인수 방식으로 호출해 보자.


>>> personal_info(name="홍길동", age=30, address="서울시 용산구 이촌동")
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


  • 키워드 인수를 사용하니 함수를 호출할 때 인수의 용도가 명확하게 보인다.


  • 특히 키워드 인수를 사용하면 다음과 같이 인수의 순서를 맞추지 않아도 키워드에 해당하는 값이 들어간다.


>>> personal_info(age=30, address="서울시 용산구 이촌동", name="홍길동")
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


  • 참고로 print 함수에서 사용했던 sep, end도 키워드 인수이다.


print(10, 20, 30, sep=":", end="")


5. 키워드 인수와 딕셔너리 언패킹 사용하기

  • 이번에는 딕셔너리를 사용해서 키워드 인수로 값을 넣는 언패킹을 사용해 보자.


  • 다음과 같이 딕셔너리 앞에 **(애스터리크 두 개)를 붙여서 함수에 넣어준다.


함수(**딕셔너리)


  • 먼저 personal_info 함수를 만든다.


>>> def personal_info(name, age, address):
...     print("이름: ", name)
...     print("나이: ", age)
...     print("주소: ", address)
...


  • 이제 딕셔너리에 "키워드": 값 형식으로 인수를 저장하고, 앞에 **를 붙여서 함수에 넣어준다.
  • 이때 딕셔너리의 키워드(키)는 반드시 문자열 형태가 되어야 한다.


>>> x = {"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"}

>>> personal_info(**x)
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


  • **x처럼 딕셔너리를 언패킹하면 딕셔너리의 값들이 함수의 인수로 들어간다.
  • 즉, personal_info(name="홍길동", age=30, address="서울시 용산구 이촌동") 또는 personal_info("홍길동", 30, "서울시 용산구 이촌동")과 똑같은 동작이 된다.


002


  • 딕셔너리 변수 대신 딕셔너리 앞에 바로 **를 붙여도 동작은 같다.


>>> personal_info(**{"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"})
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


  • 딕셔너리 언패킹을 사용할 때는 함수의 매개변수 이름과 딕셔너리의 키 이름이 같아야 한다.
  • 또한, 매개변수 개수와 딕셔너리 키의 개수도 같아야 한다.
  • 만약 이름과 개수가 다르면 함수를 호출할 수 없다.
  • 여기서는 함수를 def personal_info(name, age, address):로 만들었으므로 딕셔너리도 똑같이 맞춰주어야 한다.


1) **를 두 번 사용하는 이유

  • 딕셔너리를 두 번 *를 사용하는 이유는 딕셔너리는 키-값 쌍 형태로 값이 저장되어 있기 때문이다.


  • 먼저 다음과 같이 *를 한 번만 사용해서 함수를 호출해 보자.


>>> x = {"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"}

>>> personal_info(*x)
이름: name
나이: age
주소: address


  • personal_info*x를 넣으면 x의 키가 출력된다.
  • 즉, 딕셔너리를 한 번 언패킹하면 키를 사용한다는 뜻이 된다.


  • 따라서 다음과 같이 **처럼 딕셔너리를 두 번 언패킹하여 값을 사용하도록 만들어야 한다.


>>> x = {"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"}

>>> personal_info(**x)
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


2) 키워드 인수를 사용하는 가변 인수 함수 만들기

  • 다음과 같이 키워드 인수를 사용하는 가변 인수 함수는 매개변수 앞에 **를 붙여서 만든다.


def 함수이름(**매개변수):
    코드


  • 함수를 만들 때 괄호 안에 **kwargs와 같이 매개변수 앞에 **를 붙인다.


>>> def personal_info(**kwargs):
...     for kw, arg in kwargs.items():
...         print(kw, ": ", arg, sep="")
...


  • personal_info 함수에 키워드와 값을 넣어서 실행해 보자.
  • 값을 한 개 넣어도 되고, 세 개 넣어도 된다.


>>> personal_info(name="홍길동")
name: 홍길동
>>> personal_info(name="홍길동", age=30, address="서울시 용산구 이촌동")
name: 홍길동
age: 30
address: 서울시 용산구 이촌동


  • 다음과 같이 딕셔너리 언패킹을 사용해도 된다.


>>> x = {"name": "홍길동"}
>>> personal_info(**x)
name: 홍길동

>>> y = {"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"}
>>> personal_info(**y)
name: 홍길동
age: 30
address: 서울시 용산구 이촌동


  • 딕셔너리에 들어있는 값이 그대로 출력되었다.
  • 즉, 딕셔너리 x{"name": "홍길동"}이므로 personal_info(**x)로 호출하면 personal_info(name="홍길동")과 같고, 딕셔너리 y{"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"}이므로 personal_info(name="홍길동", age=30, address="서울시 용산구 이촌동")과 같다.
  • 이처럼 함수를 만들 때 def personal_info(**kwargs):와 같이 매개변수에 **를 붙여주면 키워드 인수를 사용하는 가변 인수 함수를 만들 수 있고, 이런 함수를 호출할 때는 키워드와 인수를 각각 넣거나 딕셔너리 언패킹을 사용하면 된다.


  • 보통 **kwargs를 사용한 가변 인수 함수는 다음과 같이 함수 안에서 특정 키가 있는지 확인한 뒤 해당 기능을 만든다.


def personal_info(**kwargs):
    if "name" in kwargs:
        print("이름: ", kwargs["name"])

    if "age" in kwargs:
        print("나이: ", kwargs["age"])

    if "address" in kwargs:
        print("주소: ", kwargs["address"])


고정 인수와 가변 인수(키워드 인수)를 함께 사용하기

  • 고정 인수와 가변 인수(키워드 인수)를 함께 사용할 때는 다음과 같이 고정 매개변수를 먼저 지정하고 나서 매개변수에 **를 붙여주면 된다.


>>> def personal_info(name, **kwargs):
...     print(name)
...     print(kwargs)
...

>>> personal_info("홍길동")
홍길동
{}
>>> personal_info("홍길동", age=30, addres="서울시 용산구 이촌동")
홍길동
{'age': 30, 'address': '서울시 용산구 이촌동'}
>>> personal_info(**{"name": "홍길동", "age": 30, "address": "서울시 용산구 이촌동"})
홍길동
{'age': 30, 'address': '서울시 용산구 이촌동'}


  • 단, 이때 def personal_info(**kwargs, name):처럼 **kwargs가 고정 매개변수보다 앞쪽에 오면 안 된다.
  • 매개변수 순서에서 **kwargs는 반드시 가장 뒤쪽에 와야 한다.


위치 인수와 키워드 인수를 함께 사용하기

  • 함수에서 위치 인수를 받는 *args와 키워드 인수를 받는 **kwargs를 함께 사용할 수도 있다.


  • 다음과 같이 함수의 매개변수를 *args, **kwargs로 지정하면 위치 인수와 키워드 인수를 함께 사용한다.


>>> def custom_print(*args, **kwargs):
...     print(*args, **kwargs)
...

>>> custom_print(1, 2, 3, sep=":", end="")
1:2:3


  • 단, 이때 def custom_print(**kwargs, *args):처럼 **kwargs*args보다 앞쪽에 오면 안 된다.
  • 매개변수 순서에서 **kwargs는 반드시 가장 뒤쪽에 와야 한다.
  • 특히 고정 매개변수와 *args, **kwargs를 함께 사용한다면 def custom_print(a, b, *args, **kwargs):처럼 매개변수는 고정 매개변수, *args, **kwargs 순으로 지정해야 한다.


6. 매개변수에 초깃값 지정하기

  • 인수를 생략할 때는 함수의 매개변수에 초깃값을 지정하면 된다.


  • 초깃값은 다음과 같이 함수를 만들 때 매개변수=값 형식으로 지정한다.


def 함수이름(매개변수=):
    코드


  • 매개변수의 초깃값은 주로 사용하는 값이 있으면서 가끔 다른 값을 사용해야 할 때 활용한다.


  • 다음과 같이 personal_info 함수에서 매개변수 address의 초깃값을 "비공개"로 지정해 보자.


>>> def personal_info(name, age, address="비공개"):
...     print("이름: ", name)
...     print("나이: ", age)
...     print("주소: ", address)
...


  • address는 초깃값이 있으므로 personal_info는 다음과 같이 address 부분을 비워 두고 호출할 수 있다.


>>> personal_info("홍길동", 30)
이름: 홍길동
나이: 30
주소: 비공개


  • 매개변수에 초깃값이 지정되어 있더라도 값을 넣으면 해당 값이 전달된다.


>>> personal_info("홍길동", 30, "서울시 용산구 이촌동")
이름: 홍길동
나이: 30
주소: 서울시 용산구 이촌동


1) 초깃값이 지정된 매개변수의 위치

  • 매개변수의 초깃값을 지정할 때 한 가지 주의할 점이 있는데, 다음과 같이 초깃값이 지정된 매개변수 다음에는 초깃값이 없는 매개변수가 올 수 없다.


>>> def personal_info(name, address="비공개", age):
...     print("이름: ", name)
...     print("나이: ", age)
...     print("주소: ", address)
...
SyntaxError: non-default argument follows default argument


  • 함수를 만들어보면 문법 에러가 발생하는데, 함수를 이렇게 만들어버리면 personal_info("홍길동", 30)으로 함수를 호출했을 때 30이 어디로 들어가야 할지 알 수가 없기 때문이다.


  • 다음과 같이 초깃값이 지정된 매개변수는 뒤쪽에 몰아주면 된다.


def personal_info(name, age, address="비공개"):
def personal_info(name, age=0, address="비공개"):
def personal_info(name="비공개", age=0, address="비공개"):

References