C.W.K.
Stream
Lesson 04 of 07 · published

함수 — 정의 / 인자 / 다양한 파라미터 종류

~25 min · function, def, arguments, kwargs, default

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

함수는 first-class 객체

Python 에서 함수는 값이야. 인자로 넘기고, 다른 함수에서 반환하고, list / dict 에 저장하고, 이름에 할당할 수 있어. def f(): pass 는 함수 객체 만들고 이름 f 를 거기 바인딩. 특별한 경우가 아니야 — x = 5 와 같은 종류의 바인딩, 그냥 오른쪽이 함수일 뿐.

네 가지 파라미터 종류 — / 와 * 구분자

Python 파라미터는 positional-only (위치로만 호출, 구분자 /), positional-or-keyword (디폴트 — 둘 다), keyword-only (이름으로만, 구분자 *), variadic — 추가 위치 인자는 *args, 추가 키워드 인자는 **kwargs. 대부분 함수는 positional-or-keyword 만. 라이브러리 작성자는 구분자로 API 모양 잠가.

디폴트 값 — 그리고 또 그 mutable 함정

디폴트 값은 *함수 정의 시점에 한 번* 평가돼. immutable 디폴트 (숫자, 문자열, None, tuple) 면 OK. mutable 디폴트 (list, dict, set) 면 버그 자석 — 같은 객체가 모든 호출에 재사용. 해결책은 None sentinel 패턴 — def f(x=None): if x is None: x = []. lesson 2 에서 봤어. 그만큼 중요해.

*args 와 **kwargs — 양 방향

함수 시그니처에서 *args 는 추가 위치 인자를 tuple 로 패킹, **kwargs 는 추가 키워드 인자를 dict 로 패킹. 호출 사이트에선 *** 가 *반대로 unpack* — f(*my_list, **my_dict). 같은 문법, 컨텍스트에 따라 반대 의미.

lambda — 작은 익명 함수

lambda x: x * 2 는 한 식짜리 함수. def f(x): return x * 2 와 같지만 인라인. sortedkey 인자, 빠른 콜백, 한 번 쓰고 안 쓸 함수 할당에 좋아. 다중 문장 로직을 lambda 로 짜지 마 — def 써.

원칙: 타입 힌트 (typing 트랙에서) 가 함수가 뭘 기대하는지에 대한 최고의 문서. def send(to: str, body: str, *, retry: int = 3) -> bool: 가 60 글자에 docstring 세 단락보다 더 많이 말해줘.

Code

함수는 first-class — 넘기고, 저장하고, 반환·python
def double(x):
    return x * 2

def triple(x):
    return x * 3

# 인자로
def apply(fn, value):
    return fn(value)

print(apply(double, 5))    # 10
print(apply(triple, 5))    # 15

# dict 에 저장
ops = {"x2": double, "x3": triple}
print(ops["x2"](7))        # 14

# 함수에서 함수 반환
def multiplier(n):
    def inner(x):
        return x * n
    return inner

times_5 = multiplier(5)
print(times_5(10))         # 50
네 가지 파라미터 종류 + 구분자·python
# / 가 경계 — 왼쪽은 모두 positional-only
# * 가 경계 — 오른쪽은 모두 keyword-only
def f(p1, p2, /, normal, *, kw1, kw2=10):
    return p1, p2, normal, kw1, kw2

# 유효
print(f(1, 2, 3, kw1=4))                    # (1, 2, 3, 4, 10)
print(f(1, 2, normal=3, kw1=4, kw2=99))     # (1, 2, 3, 4, 99)

# 무효
try:
    f(p1=1, p2=2, normal=3, kw1=4)         # p1/p2 는 positional-only
except TypeError as e:
    print(e)

try:
    f(1, 2, 3, 4)                          # kw1 은 키워드여야
except TypeError as e:
    print(e)
디폴트 값 — mutable 함정·python
# 안 좋음
def bad(item, history=[]):
    history.append(item)
    return history

print(bad("a"))    # ['a']
print(bad("b"))    # ['a', 'b']    <- 공유!

# 좋음
def good(item, history=None):
    if history is None:
        history = []
    history.append(item)
    return history

print(good("a"))   # ['a']
print(good("b"))   # ['b']         <- 새 list
*args / **kwargs — 패킹과 unpacking·python
# 시그니처에서 — 추가분 패킹
def summary(name, *items, **flags):
    print(f"name={name}, items={items}, flags={flags}")

summary("a", 1, 2, 3, debug=True, verbose=False)
# name=a, items=(1, 2, 3), flags={'debug': True, 'verbose': False}

# 호출 사이트에서 — 반대 방향 unpack
args = ("a", 1, 2, 3)
kwargs = {"debug": True}
summary(*args, **kwargs)

# 일반 호출 forwarding (decorator 패턴 미리보기)
def wrap(fn):
    def wrapper(*args, **kwargs):
        return fn(*args, **kwargs)
    return wrapper
lambda — 한 식짜리 함수·python
# dict list 를 필드로 정렬
people = [{"name": "a", "age": 30}, {"name": "b", "age": 25}]
print(sorted(people, key=lambda p: p["age"]))

# filter + map (보통 컴프리헨션이 이김)
nums = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)               # [2, 4]

# 다중 기준 빠른 sort key
records = [("b", 2), ("a", 3), ("a", 1), ("b", 1)]
print(sorted(records, key=lambda r: (r[0], r[1])))
# [('a', 1), ('a', 3), ('b', 1), ('b', 2)]

External links

Exercise

함수 report(title, /, *items, sep=' | ', limit=None, **meta) 작성 — title 은 positional-only, items 는 추가 위치 인자 모음, sep/limit 는 keyword-only with 디폴트, meta 는 나머지 모음. 함수는 title 출력 → 최대 limit 개 (None 이면 전체) item 을 sep 로 join → meta 를 key=value 라인들. 최소 4 가지 호출로 테스트 — report("a", 1, 2, 3, limit=2, color='red') 포함.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.