본문으로 건너뛰기
김신건의 로그

[Python] 함수 기초: def, 인수, return

· 수정 · 📖 약 1분 · 526자/단어 #python #function #def #args #kwargs #basics
python function, python def, args kwargs, 함수 인수, positional keyword

def

def 문으로 함수를 정의한다. 함수도 **일급 객체(first-class)**라 변수에 할당하고 인자로 전달할 수 있다.

def add(a, b):
    """두 수의 합 반환."""
    return a + b

f = add               # 함수 객체 참조
print(f(3, 4))        # 7
print(add.__doc__)    # 두 수의 합 반환.
print(add.__name__)   # add

인수 종류

Python 함수 시그니처는 6가지 매개변수 종류를 조합한다.

def f(pos_only, /, pos_or_kw, *args, kw_only, **kwargs):
    ...
위치종류설명
pos_onlypositional-only (3.8+)/ 앞: 키워드로 못 부름
/* 사이positional-or-keyword둘 다 가능 (기본)
*argsvar-positional가변 위치 인수 → tuple
* 또는 *argskeyword-only키워드로만 부를 수 있음
**kwargsvar-keyword가변 키워드 → dict
python
def demo(a, b, /, c, d, *args, e, f=10, **kwargs):
  print(f"a={a}, b={b}, c={c}, d={d}")
  print(f"args={args}, e={e}, f={f}, kwargs={kwargs}")

demo(1, 2, 3, d=4, e=5, x=99, y=100)
결과
a=1, b=2, c=3, d=4
args=(), e=5, f=10, kwargs={'x': 99, 'y': 100}

기본값 인수

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}"

greet("Alice")                    # "Hello, Alice"
greet("Bob", "Hi")                # "Hi, Bob"
greet("Carol", greeting="Hey")    # "Hey, Carol"

주의: 기본값은 한 번만 평가 (가변 기본값 함정)

python
def append_bad(item, items=[]):    # WRONG
  items.append(item)
  return items

print(append_bad(1))    # [1]
print(append_bad(2))    # [1, 2] (공유됨!)

def append_good(item, items=None):
  if items is None:
      items = []
  items.append(item)
  return items

print(append_good(1))   # [1]
print(append_good(2))   # [2] (매번 새로)
결과
[1]
[1, 2]
[1]
[2]

기본값 표현식은 def가 평가될 때 단 한 번 계산된다. 가변 객체(list, dict)는 절대 기본값으로 쓰지 말 것. 관용구: None 센티넬.

*args, **kwargs

가변 인수 수집·전달에 사용.

python
def variadic(*args, **kwargs):
  print(args, kwargs)

variadic(1, 2, 3, x=10, y=20)

# 호출 시 언패킹
def add3(a, b, c):
  return a + b + c

nums = [1, 2, 3]
print(add3(*nums))             # 1, 2, 3

params = {"a": 1, "b": 2, "c": 3}
print(add3(**params))
결과
(1, 2, 3) {'x': 10, 'y': 20}
6
6

함수 전달 시 그대로 통과시키는 패턴 (decorator, wrapper):

def wrapper(*args, **kwargs):
    log.info("called", args=args, kwargs=kwargs)
    return inner(*args, **kwargs)

keyword-only 인수

*args 뒤(또는 단독 * 뒤)에 오는 인수는 키워드로만 호출 가능.

def connect(host, port, *, timeout=30, retries=3):
    ...

connect("localhost", 8080)                       # OK
connect("localhost", 8080, timeout=60)           # OK
connect("localhost", 8080, 60)                   # TypeError

API에 옵션이 많을 때 잘못된 위치 인수 전달을 방지한다.

positional-only 인수 (3.8+, PEP 570)

/ 앞 매개변수는 위치로만 호출 가능. 키워드 이름을 API 계약에서 빼고 싶을 때 유용.

def divmod_(a, b, /):
    return a // b, a % b

divmod_(10, 3)              # OK
divmod_(a=10, b=3)          # TypeError

내장 함수의 동작과 일치시키거나, 향후 이름 변경에 자유롭게 하기 위함.

return

명시적 return 없으면 None 반환. 다중 값은 튜플로.

def parse(line):
    parts = line.split()
    if not parts:
        return None           # 명시적 조기 반환
    return parts[0], int(parts[1])   # 튜플 (다중값)

key, value = parse("count 42")

함수 어노테이션 (타입 힌트)

def greet(name: str, age: int = 0) -> str:
    return f"Hello {name}, {age}"

# 어노테이션 조회
print(greet.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}

런타임에 강제하지 않지만 mypy, pyright 같은 타입 체커가 활용. 자세한 건 py-type-hints 참고.

람다 (anonymous function)

단일 표현식만 가능한 익명 함수.

square = lambda x: x ** 2
print(square(5))    # 25

# 정렬 키
words = ["apple", "pie", "banana"]
words.sort(key=lambda s: len(s))

# map/filter
squared = list(map(lambda x: x ** 2, range(5)))

복잡한 람다보다 def로 분리하는 게 가독성 좋음.

일급 함수와 클로저

함수는 객체라서 다른 함수에 전달, 반환, 변수 할당 가능.

def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

counter = make_counter()
print(counter(), counter(), counter())  # 1 2 3

nonlocal 없이는 count에 재할당하면 새 로컬 변수가 생긴다.

데코레이터 (간단 소개)

함수를 받아 함수를 반환하는 함수.

def log(fn):
    def wrapper(*args, **kwargs):
        print(f"calling {fn.__name__}")
        return fn(*args, **kwargs)
    return wrapper

@log
def add(a, b):
    return a + b

# 동등: add = log(add)
add(1, 2)    # "calling add" 출력 후 3

상세는 py-decorator 페이지에서.

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기