Study/Python

[Python] 함수(Function)와 람다 표현식(Lambda)

the.Dev.Cat 2026. 3. 7. 23:26

 

동빈나 채널의 파이썬 문법 부수기 유튜브 강의를 참고하여 정리한 내용이다.

 

함수는 특정 작업을 하나의 단위로 묶은 것이다.

파이썬 코딩테스트에서 함수를 잘 쓰면 복잡한 로직을 정리할 수 있고, 재귀 구현도 자연스럽게 된다.

내장 함수들도 어떤 게 있는지 알아두면 바퀴를 다시 만드는 일을 줄일 수 있다.

 


 

함수 종류

파이썬 함수는 크게 두 가지다.

  • 내장 함수: 파이썬이 기본 제공하는 함수. print(), input(), len(), range()
  • 사용자 정의 함수: def 키워드로 직접 만드는 함수

 


 

함수 정의: def

def 함수명(매개변수):
    실행할 코드
    return 반환값
def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 8

 

return이 없으면 None을 반환한다.

def greet(name):
    print(f"안녕, {name}")

result = greet("Alice")  # 안녕, Alice
print(result)  # None

 


 

매개변수와 반환값

def is_even(n):
    return n % 2 == 0

print(is_even(4))   # True
print(is_even(7))   # False

def absolute(n):
    if n < 0:
        return -n
    return n

print(absolute(-5))  # 5
print(absolute(3))   # 3

 

return을 만나면 즉시 함수를 빠져나온다. 뒤에 코드가 더 있어도 실행되지 않는다.

def early_return(x):
    if x < 0:
        return "음수"
    print("여기는 음수가 아닐 때만 실행됨")
    return "양수 또는 0"

print(early_return(-1))  # 음수 (print는 실행 안 됨)
print(early_return(5))   # 여기는 음수가 아닐 때만 실행됨 \n 양수 또는 0

 


 

기본값 매개변수

매개변수에 기본값을 지정하면 호출 시 생략할 수 있다.

def power(base, exponent=2):
    return base ** exponent

print(power(3))     # 9  (exponent 생략 → 기본값 2)
print(power(3, 3))  # 27
print(power(2, 10)) # 1024

 

기본값이 있는 매개변수는 기본값이 없는 매개변수 뒤에 와야 한다.

def func(a, b=10, c):  # SyntaxError: non-default argument follows default argument
    pass

def func(a, b, c=10):  # 올바름
    pass

 


 

키워드 인수

매개변수 이름을 명시해서 전달할 수 있다. 순서가 달라도 된다.

def introduce(name, age, job):
    print(f"이름: {name}, 나이: {age}, 직업: {job}")

# 위치 인수
introduce("Alice", 25, "개발자")

# 키워드 인수 - 순서 무관
introduce(age=25, job="개발자", name="Alice")
introduce("Alice", job="개발자", age=25)

 

기본값 매개변수와 조합하면 선택적으로 값을 전달할 수 있다.

def connect(host, port=3306, timeout=30):
    print(f"{host}:{port} (timeout: {timeout}s)")

connect("localhost")                  # localhost:3306 (timeout: 30s)
connect("localhost", timeout=10)      # localhost:3306 (timeout: 10s)
connect("localhost", 5432, 60)        # localhost:5432 (timeout: 60s)

 


 

가변 인수: *args, **kwargs

인수 개수가 정해지지 않을 때 쓴다.

*args - 위치 인수를 튜플로 받기

def my_sum(*args):
    total = 0
    for n in args:
        total += n
    return total

print(my_sum(1, 2, 3))        # 6
print(my_sum(1, 2, 3, 4, 5))  # 15
print(my_sum())                # 0

 

**kwargs - 키워드 인수를 사전으로 받기

def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, job="개발자")
# name: Alice
# age: 25
# job: 개발자

 

조합

def func(a, b, *args, **kwargs):
    print(f"a={a}, b={b}")
    print(f"args={args}")
    print(f"kwargs={kwargs}")

func(1, 2, 3, 4, 5, x=10, y=20)
# a=1, b=2
# args=(3, 4, 5)
# kwargs={'x': 10, 'y': 20}

 


 

전역변수 vs 지역변수

함수 안에서 만든 변수는 지역변수다. 함수 밖에서는 접근할 수 없다.

x = 10  # 전역변수

def func():
    y = 20  # 지역변수
    print(x)  # 전역변수 읽기 - 가능
    print(y)

func()
print(x)  # 10
print(y)  # NameError: name 'y' is not defined

 

global 키워드

함수 안에서 전역변수를 수정하려면 global을 선언해야 한다.

count = 0

def increment():
    global count
    count += 1

increment()
increment()
print(count)  # 2

 

global 없이 수정하면 새 지역변수가 만들어진다.

count = 0

def bad_increment():
    count += 1  # UnboundLocalError: local variable 'count' referenced before assignment

bad_increment()

 

읽기는 되지만 수정은 global 없이 안 된다.

코딩테스트에서 DFS/BFS 방문 배열이나 카운터 변수를 전역으로 쓸 때 자주 쓰는 패턴이다.

# 코딩테스트 실전 패턴
visited = []
result = 0

def dfs(node):
    global result
    if node not in visited:
        visited.append(node)
        result += 1

 


 

여러 값 반환

파이썬은 여러 값을 반환할 수 있다. 내부적으로는 튜플로 묶여서 반환된다.

def min_max(nums):
    return min(nums), max(nums)

lo, hi = min_max([3, 1, 4, 1, 5, 9])
print(lo, hi)  # 1 9

# 튜플로 받을 수도 있다
result = min_max([3, 1, 4, 1, 5, 9])
print(result)       # (1, 9)
print(result[0])    # 1

 


 

람다 표현식

이름 없는 함수를 한 줄로 만든다.

# def 함수
def add(x, y):
    return x + y

# 람다 - 같은 기능
add = lambda x, y: x + y

print(add(3, 5))  # 8
# 매개변수 하나
square = lambda x: x ** 2
print(square(4))  # 16

# 조건부 표현식과 조합
abs_val = lambda x: x if x >= 0 else -x
print(abs_val(-5))  # 5

 

람다는 단순한 함수를 인수로 전달할 때 주로 쓴다. 복잡한 로직에는 def를 쓰는 게 낫다.

 


 

람다 + sorted, map, filter

sorted()와 key

# 절댓값 기준으로 정렬
nums = [-5, 2, -1, 4, -3]
sorted_nums = sorted(nums, key=lambda x: abs(x))
print(sorted_nums)  # [-1, 2, -3, 4, -5]

# 문자열 길이 기준으로 정렬
words = ["banana", "apple", "fig", "cherry"]
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words)  # ['fig', 'apple', 'banana', 'cherry']

# 튜플 두 번째 원소 기준으로 정렬
pairs = [(1, 3), (2, 1), (3, 2)]
sorted_pairs = sorted(pairs, key=lambda p: p[1])
print(sorted_pairs)  # [(2, 1), (3, 2), (1, 3)]

# 내림차순
sorted_desc = sorted(nums, key=lambda x: abs(x), reverse=True)
print(sorted_desc)  # [-5, 4, -3, 2, -1]

 

map()

이터러블의 각 원소에 함수를 적용한다. list()로 감싸야 결과를 리스트로 볼 수 있다.

nums = [1, 2, 3, 4, 5]

squares = list(map(lambda x: x ** 2, nums))
print(squares)  # [1, 4, 9, 16, 25]

# def 함수도 전달 가능
def double(x):
    return x * 2

doubled = list(map(double, nums))
print(doubled)  # [2, 4, 6, 8, 10]

 

filter()

조건에 맞는 원소만 걸러낸다.

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)  # [2, 4, 6, 8, 10]

odds = list(filter(lambda x: x % 2 != 0, nums))
print(odds)   # [1, 3, 5, 7, 9]

리스트 컴프리헨션으로도 같은 결과를 낼 수 있다. 파이썬에서는 리스트 컴프리헨션이 더 가독성이 좋은 경우가 많다.

# map 대신 리스트 컴프리헨션
squares = [x ** 2 for x in nums]

# filter 대신 리스트 컴프리헨션
evens = [x for x in nums if x % 2 == 0]

 


 

주요 내장 함수

코딩테스트에서 자주 쓰는 것들만 모았다.

nums = [3, 1, 4, 1, 5, 9, 2, 6]

print(min(nums))        # 1
print(max(nums))        # 9
print(sum(nums))        # 31
print(len(nums))        # 8
print(sorted(nums))     # [1, 1, 2, 3, 4, 5, 6, 9]
print(list(reversed(nums)))  # [6, 2, 9, 5, 1, 4, 1, 3]

# abs: 절댓값
print(abs(-7))  # 7

# round: 반올림
print(round(3.14159, 2))  # 3.14

# pow: 거듭제곱 (세 번째 인수로 모듈러 연산 가능)
print(pow(2, 10))       # 1024
print(pow(2, 10, 100))  # 1024 % 100 = 24

# divmod: 몫과 나머지를 튜플로
print(divmod(17, 5))  # (3, 2)
q, r = divmod(17, 5)
print(q, r)  # 3 2

# all, any
print(all([True, True, True]))   # True
print(all([True, False, True]))  # False
print(any([False, False, True])) # True
print(any([False, False, False]))# False

# 조건 검사
nums = [2, 4, 6, 8]
print(all(n % 2 == 0 for n in nums))  # True - 모두 짝수
print(any(n > 5 for n in nums))       # True - 하나 이상이 5 초과
함수 설명 예시
min(iterable) 최솟값 min([3, 1, 4]) → 1
max(iterable) 최댓값 max([3, 1, 4]) → 4
sum(iterable) 합계 sum([1, 2, 3]) → 6
len(iterable) 길이 len([1, 2, 3]) → 3
sorted(iterable) 정렬된 새 리스트 sorted([3, 1, 2]) → [1, 2, 3]
reversed(iterable) 역순 이터레이터 list(reversed([1,2,3])) → [3, 2, 1]
enumerate(iterable) 인덱스, 값 쌍 enumerate(['a','b'])
zip(*iterables) 병렬 순회 zip([1,2], ['a','b'])
map(func, iterable) 함수 적용 list(map(int, ['1','2']))
filter(func, iterable) 조건 필터링 list(filter(None, [0,1,2]))
abs(x) 절댓값 abs(-3) → 3
pow(x, y) 거듭제곱 pow(2, 8) → 256
divmod(x, y) 몫과 나머지 divmod(17, 5) → (3, 2)
all(iterable) 모두 True? all([1, 2, 3]) → True
any(iterable) 하나라도 True? any([0, 0, 1]) → True

 


 

에러 상황

TypeError - 인수 개수 불일치

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

add(1)          # TypeError: add() missing 1 required positional argument: 'b'
add(1, 2, 3)    # TypeError: add() takes 2 positional arguments but 3 were given

 

UnboundLocalError - global 없이 전역변수 수정

count = 0

def increment():
    count += 1  # UnboundLocalError: local variable 'count' referenced before assignment

 

RecursionError - 재귀 깊이 초과

def factorial(n):
    return n * factorial(n - 1)  # 종료 조건이 없음

factorial(5)  # RecursionError: maximum recursion depth exceeded
# 올바른 재귀
def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 120

 

파이썬 기본 재귀 깊이는 1000이다. 더 깊은 재귀가 필요하면 sys.setrecursionlimit()으로 늘릴 수 있다.

import sys
sys.setrecursionlimit(100000)

 

코딩테스트에서 재귀를 쓸 때는 코드 상단에 이 줄을 넣는 게 안전하다.