함수 정의 시 Python 선택적 인수 사용

2023. 12. 27. 16:00python/basic

자신만의 함수를 정의하는 것은 깔끔하고 효과적인 코드를 작성하는 데 필수적인 기술입니다. 이 튜토리얼에서는 선택적 인수를 취하는 Python 함수를 정의하는 데 사용할 수 있는 기술을 살펴보겠습니다. Python의 선택적 인수를 익히면 더욱 강력하고 유연한 함수를 정의할 수 있습니다.

이 튜토리얼에서는 다음 내용을 학습합니다.

  • 매개변수와 인수의 차이점
  • 선택적 인수 및 기본 매개변수 값을 사용하여 함수를 정의하는 방법
  • args 및 kwargs를 사용하여 함수를 정의하는 방법
  • 선택적 인수에 대한 오류 메시지 처리 방법

코드 재사용을 위해 Python에서 함수 만들기

함수의 주요 목적은 필요할 때마다 다른 입력을 사용하여 필요할 때마다 함수 내에서 코드를 재사용할 수 있도록 하는 것입니다.

함수를 사용하면 Python 어휘가 확장됩니다. 이를 통해 문제에 대한 해결책을 보다 명확하고 간결하게 표현할 수 있습니다.

Python에서는 관례적으로 do_something()과 같이 밑줄로 구분된 단어와 소문자를 사용하여 함수 이름을 지정해야 합니다. 이러한 규칙은 Python의 스타일 가이드인 PEP 8에 설명되어 있습니다. 호출할 때 함수 이름 뒤에 괄호를 추가해야 합니다. 함수는 동작을 나타내므로 코드를 더 읽기 쉽게 만들기 위해 함수 이름을 동사로 시작하는 것이 가장 좋습니다.

입력 매개변수 없이 함수 정의하기

이 튜토리얼에서는 쇼핑 목록을 생성 및 유지하고 인쇄하는 기본 프로그램의 예를 사용합니다.

In [ ]:
shopping_list = {
    "Bread": 1,
    "Milk": 2,
    "Chocolate": 1,
    "Butter": 1,
    "Coffee": 1,
}

Dictionary을 사용하여 항목 이름을 키로 저장하고 각 항목을 구매해야 하는 수량을 값으로 저장합니다.

In [ ]:
# optional_params.py

shopping_list = {
    "Bread": 1,
    "Milk": 2,
    "Chocolate": 1,
    "Butter": 1,
    "Coffee": 1,
}

def show_list():
    for item_name, quantity in shopping_list.items():
        print(f"{quantity}x {item_name}")

show_list()

이 예에서는 사전shopping_list이 전역 변수이므로 입력 매개변수가 필요하지 않습니다.

필수 입력 인수로 함수 정의

코드에서 직접 쇼핑 목록을 작성하는 대신 이제 빈 사전을 초기화하고 쇼핑 목록에 항목을 추가할 수 있는 함수를 작성할 수 있습니다.

In [ ]:
# optional_params.py

shopping_list = {}

# ...

def add_item(item_name, quantity):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item("Bread", 1)
print(shopping_list)

함수 서명에 두 개의 매개변수가 포함되었습니다.

  1. item_name
  2. quantity

호출 시 입력하는 인수add_item()는 필수 인수입니다. 인수 없이 함수를 호출하려고 하면 오류가 발생합니다.

In [ ]:
# optional_params.py

shopping_list = {}

def add_item(item_name, quantity):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item()
print(shopping_list)

기본값과 함께 Python 선택적 인수 사용m

입력 매개변수에 지정된 기본값

In [ ]:
# optional_params.py

shopping_list = {}

def add_item(item_name, quantity=1):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

add_item("Bread")
add_item("Milk", 2)
print(shopping_list)

함수 서명에서 기본값 1을 매개변수 quantity에 추가했습니다. 이는 quantity 값이 항상 1이라는 의미는 아닙니다. 함수를 호출할 때 quantity에 해당하는 인수를 전달하면 해당 인수가 매개변수 값으로 사용됩니다. 그러나 인수를 전달하지 않으면 기본값이 사용됩니다.

함수add_item()에는 이제 하나의 필수 매개변수와 하나의 선택 매개변수가 있습니다. 위의 코드 예에서는 add_item()를 두 번 호출합니다. 첫 번째 함수 호출에는 필수 매개변수 item_name에 해당하는 단일 인수가 있습니다. 이 경우 quantity의 기본값은 1입니다. 두 번째 함수 호출에는 두 개의 인수가 있으므로 이 경우 기본값은 사용되지 않습니다.

필수 및 선택 인수를 함수에 키워드 인수로 전달할 수도 있습니다. 키워드 인수는 명명된 인수라고도 할 수 있습니다

In [ ]:
add_item(item_name="Milk", quantity=2)

이제 이 튜토리얼에서 정의한 첫 번째 함수를 다시 방문하여 기본 인수도 허용하도록 리팩토링할 수 있습니다.

In [ ]:
def show_list(include_quantities=True):
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

이제 show_list()을 사용할 때 입력 인수 없이 호출하거나 부울 값을 전달할 수 있습니다.
플래그 값이 함수의 동작을 크게 변경하는 경우에는 플래그 사용을 피해야 합니다. 함수는 한 가지 일만 담당해야 합니다. 플래그를 통해 함수를 대체 경로로 푸시하려면 대신 별도의 함수를 작성하는 것이 좋습니다.

공통 기본 인수 값

입력 매개변수가 문자열이어야 하는 경우 일반적으로 사용되는 기본값은 빈 문자열("")입니다.

In [ ]:
def add_item(item_name="", quantity=1):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

두 매개변수 모두 기본값을 갖도록 함수를 수정했습니다. 따라서 입력 매개변수 없이 함수를 호출할 수 있습니다.

In [ ]:
add_item()
In [ ]:
def add_item(item_name="", quantity=1):
    if not item_name:
        quantity = 0
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

이 버전에서는 항목이 함수에 전달되지 않으면 함수는 수량을 0로 설정합니다.
기본값으로 자주 사용되는 또 다른 일반적인 값은 None입니다. 이는 실제로는 null 값을 나타내는 객체이지만 아무것도 나타내지 않는 Python의 방식입니다.

기본 인수로 사용하면 안 되는 데이터 유형

위의 예에서는 정수와 문자열을 기본값으로 사용했으며 None은 또 다른 일반적인 기본값입니다. 기본값으로 사용할 수 있는 유일한 데이터 유형은 아닙니다. 그러나 모든 데이터 유형을 사용해야 하는 것은 아닙니다.
항목 이름과 수량을 포함하는 사전을 앞서 정의한 함수에 입력 매개변수로 추가할 수 있습니다. 모든 인수를 필수 인수로 만드는 것부터 시작할 수 있습니다.

In [ ]:
def add_item(item_name, quantity, shopping_list):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

함수를 호출하려면 함수에서 반환된 데이터를 변수에 할당해야 합니다.

In [ ]:
# optional_params.py

hardware_store_list = {}
supermarket_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

hardware_store_list = add_item("Nails", 1, hardware_store_list)
hardware_store_list = add_item("Screwdriver", 1, hardware_store_list)
hardware_store_list = add_item("Glue", 3, hardware_store_list)

supermarket_list = add_item("Bread", 1, supermarket_list)
supermarket_list = add_item("Milk", 2, supermarket_list)

show_list(hardware_store_list)
show_list(supermarket_list)
In [ ]:
# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list={}):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
show_list(clothes_shop_list)

그러나 이 코드에는 예상치 못한 잘못된 결과를 초래할 수 있는 심각한 결함이 있습니다.shopping_list에 해당하는 인수 없이 add_item()를 사용하여 전자제품 매장에서 필요한 품목에 대한 새 쇼핑 목록을 추가할 수 있습니다. 그러면 새 빈 사전을 생성할 수 있는 기본값이 사용됩니다.

In [ ]:
# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list={}):
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
electronics_store_list = add_item("USB cable", 1)
show_list(clothes_shop_list)
show_list(electronics_store_list)

함수를 호출할 때마다 add_item()의 출력을 다른 변수에 할당했지만 두 쇼핑 목록은 모두 동일합니다. 문제는 사전이 변경 가능한 데이터 유형이기 때문에 발생합니다.

함수를 정의할 때 빈 사전을 매개변수인 shopping_list의 기본값으로 할당했습니다. 함수를 처음 호출하면 이 사전은 비어 있습니다. 그러나 사전은 변경 가능한 유형이므로 사전에 값을 할당하면 기본 사전이 더 이상 비어 있지 않습니다.

함수를 두 번째로 호출하고 shopping_list의 기본값이 다시 필요한 경우, 기본 사전은 함수를 처음 호출할 때 채워졌으므로 더 이상 비어 있지 않습니다. 동일한 함수를 호출하므로 메모리에 저장된 동일한 기본 사전을 사용하고 있습니다.

이 동작은 불변 데이터 유형에서는 발생하지 않습니다. 이 문제에 대한 해결책은 None과 같은 다른 기본값을 사용한 다음 선택적 인수가 전달되지 않을 때 함수 내에 빈 사전을 만드는 것입니다.

In [ ]:
# optional_params.py

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_item(item_name, quantity, shopping_list=None):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

clothes_shop_list = add_item("Shirt", 3)
electronics_store_list = add_item("USB cable", 1)
show_list(clothes_shop_list)
show_list(electronics_store_list)

if 문을 사용하여 사전이 인수로 전달되었는지 확인할 수 있습니다. None의 허위 특성에 의존해서는 안 되며 대신 인수가 None인지 명시적으로 확인해야 합니다.

입력 인수와 관련된 오류 메시지

직면하게 되는 가장 일반적인 오류 메시지 중 하나는 필수 인수가 있는 함수를 호출했지만 함수 호출에서 인수를 전달하지 않은 경우입니다.

In [ ]:
# optional_params.py

# ...

def add_item(item_name, quantity, shopping_list=None):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

add_item()

여기에서는 필수 인수 및 를 전달하지 않고 add_item()를 호출합니다. 필수 인수가 누락될 때마다 item_namequantityTypeError가 표시됩니다.

add_item()의 정의에서 기본값이 있는 매개변수와 기본값이 없는 매개변수의 순서를 바꿀 수 있습니다.

In [ ]:
# optional_params.py

# ...

def add_item(shopping_list=None, item_name, quantity):
    if shopping_list is None:
        shopping_list = {}
    if item_name in shopping_list.keys():
        shopping_list[item_name] += quantity
    else:
        shopping_list[item_name] = quantity

    return shopping_list

기본값이 없는 매개변수는 항상 기본값이 있는 매개변수 앞에 와야 합니다. 위의 예에서 item_name 및 quantity에는 항상 값이 인수로 할당되어야 합니다. 기본값이 있는 매개변수를 먼저 배치하면 함수 호출이 모호해집니다. 처음 두 개의 필수 인수 뒤에는 선택적인 세 번째 인수가 올 수 있습니다.

args 및 사용kwargs

가변 개수의 입력 인수와 키워드로 함수를 정의하려면 args 및 kwargs에 대해 배워야 합니다.

임의 개수의 인수를 허용하는 함수

In [ ]:
some_items = ["Coffee", "Tea", "Cake", "Bread"]

변수 some_items는 ist을 가리키며 list에는 4개의 항목이 있습니다. some_items를 print()에 대한 인수로 사용하면 하나의 변수가 print()에 전달됩니다.

In [ ]:
print(some_items)

그러나 print()의 괄호 안에 *some_items을 사용해야 하는 경우에는 다른 결과를 얻게 됩니다.

In [ ]:
print(*some_items)

이번에는 print()가 list이 아닌 4개의 개별 문자열을 표시합니다.

별표 또는 별 기호(*)가 시퀀스 바로 앞에 사용되는 경우(예: some_items) 시퀀스를 개별 구성 요소로 압축 해제합니다. list와 같은 시퀀스가 ​​압축 해제되면 해당 항목이 추출되어 개별 개체로 처리됩니다.

args을 사용하여 가변 개수의 입력 인수를 포함하는 함수 서명은 다음과 같습니다.

def add_items(shopping_list, *args):

In [ ]:
# optional_params.py

shopping_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_items(shopping_list, *item_names):
    for item_name in item_names:
        shopping_list[item_name] = 1

    return shopping_list

shopping_list = add_items(shopping_list, "Coffee", "Tea", "Cake", "Bread")
show_list(shopping_list)

간단한 예를 보면 item_names 매개변수에 어떤 일이 일어나는지 이해할 수 있습니다.

In [ ]:
def add_items_demo(*item_names):
    print(type(item_names))
    print(item_names)

add_items_demo("Coffee", "Tea", "Cake", "Bread")

데이터 유형을 표시하면 item_names이 튜플임을 알 수 있습니다. 따라서 모든 추가 인수는 튜플 item_names의 항목으로 할당됩니다. 그런 다음 위의 add_items() 기본 정의에서 했던 것처럼 함수 정의 내에서 이 튜플을 사용할 수 있습니다.

함수를 호출할 때 추가 인수를 추가하지 않으면 튜플은 비어 있게 됩니다.

In [ ]:
add_items_demo()

임의 개수의 키워드 인수를 허용하는 함수

매개변수가 있는 함수를 정의할 때 키워드가 아닌 인수나 키워드 인수를 사용하여 함수를 호출할 수 있습니다.

In [ ]:
def test_arguments(a, b):
    print(a)
    print(b)

test_arguments("first argument", "second argument")
In [ ]:
test_arguments(a="first argument", b="second argument")

첫 번째 함수 호출에서는 인수가 위치별로 전달되는 반면, 두 번째 함수 호출에서는 키워드로 전달됩니다. 키워드 인수를 사용하는 경우 더 이상 정의된 순서대로 인수를 입력할 필요가 없습니다.

In [ ]:
test_arguments(b="second argument", a="first argument")

함수를 정의할 때 키워드 인수를 나타내는 kwargs을 사용하여 포함할 선택적 키워드 인수를 원하는 수만큼 포함할 수 있습니다. 함수 서명은 다음과 같습니다:

def add_items(shopping_list, **kwargs):

매개변수 이름kwargs 앞에는 별표 두 개(**)가 옵니다. 이중 별표 또는 별표는 이전에 시퀀스에서 항목의 압축을 풀 때 사용한 단일 별표와 유사하게 작동합니다. 이중 별표는 매핑에서 항목의 압축을 푸는 데 사용됩니다. 매핑은 사전과 같은 항목으로 쌍을 이루는 값을 갖는 데이터 유형입니다.

In [ ]:
# optional_params.py

shopping_list = {}

def show_list(shopping_list, include_quantities=True):
    print()
    for item_name, quantity in shopping_list.items():
        if include_quantities:
            print(f"{quantity}x {item_name}")
        else:
            print(item_name)

def add_items(shopping_list, **things_to_buy):
    for item_name, quantity in things_to_buy.items():
        shopping_list[item_name] = quantity

    return shopping_list

shopping_list = add_items(shopping_list, coffee=1, tea=2, cake=1, bread=3)
show_list(shopping_list)
In [ ]:
def add_items_demo(**things_to_buy):
    print(type(things_to_buy))
    print(things_to_buy)

add_items_demo(coffee=1, tea=2, cake=1, bread=3)
In [ ]:
출처 : https://realpython.com/python-optional-arguments/