0Pricing
DSA Interview Prep · 강의

함수, 클로저, 람다

재사용 가능한 보조 함수를 정의하고 기본 인수를 사용하며, 면접 문제의 정렬과 함수형 패턴에 람다 표현식을 적용합니다.

함수, 클로저, 람다은(는) CoddyKit의 무료 DSA Interview Prep 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 DSA Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. DSA Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

파이썬에서 함수 정의하기

파이썬에서 함수는 일급 객체입니다. 함수를 전달하고, 반환하고, 저장할 수 있습니다. 이름을 잘 지은 도우미 함수는 면접 코드의 가독성을 높여 줍니다. 먼저 예외 상황을 처리하십시오.

def is_palindrome(s: str) -> bool:
    '''Return True if s reads the same forwards and backwards.'''
    s = s.lower()
    return s == s[::-1]

print(is_palindrome('Racecar'))  # True
print(is_palindrome('hello'))    # False

# Functions as values
checks = [is_palindrome]
print(checks[0]('level'))  # True

기본 인수와 키워드 인수

기본값을 사용하면 호출자가 인수를 생략할 수 있습니다. 하지만 리스트처럼 변경 가능한 기본값은 절대 사용하지 마십시오. 모든 호출자가 이를 공유하기 때문입니다. 기본값을 None으로 지정하고 함수 내부에서 리스트를 만드는 것이 해결 방법입니다. 코드를 확인해 보십시오.

# WRONG: shared mutable default
def bad_append(val, lst=[]):
    lst.append(val)
    return lst

print(bad_append(1))  # [1]
print(bad_append(2))  # [1, 2]  surprise!

# CORRECT: use None sentinel
def good_append(val, lst=None):
    if lst is None:
        lst = []
    lst.append(val)
    return lst

print(good_append(1))  # [1]
print(good_append(2))  # [2]

*args와 **kwargs

*args는 추가 위치 인수를 튜플로 모으고, **kwargs는 추가 키워드 인수를 딕셔너리로 모읍니다. 호출할 때 *를 사용하면 시퀀스의 요소를 펼칠 수도 있습니다.

def total(*args):
    return sum(args)

print(total(1, 2, 3))     # 6
print(total(1, 2, 3, 4))  # 10

# Unpack a list as positional args
point = [3, 7]
print(max(*point))   # 7

# **kwargs
def greet(**kwargs):
    name = kwargs.get('name', 'World')
    return f'Hello, {name}!'

print(greet(name='Alice'))  # Hello, Alice!

람다 표현식

lambda는 한 줄로 작성하는 작은 함수입니다. lambda params: expression과 같은 형태입니다. sorted나 max에서 임시 키로 사용하기에 안성맞춤입니다. 더 복잡한 작업에는 이름 있는 함수 정의가 더 명확하게 읽힙니다.

# Lambda as sort key
pairs = [(1, 3), (2, 1), (3, 2)]
sorted_by_second = sorted(pairs, key=lambda p: p[1])
print(sorted_by_second)  # [(2,1),(3,2),(1,3)]

# Lambda with map
double = list(map(lambda n: n * 2, [1, 2, 3]))
print(double)  # [2, 4, 6]

# Named function is clearer for complex logic
def sort_key(p):
    return (p[1], -p[0])  # secondary sort
print(sorted(pairs, key=sort_key))

중첩 함수와 클로저

클로저는 자신을 둘러싼 함수의 변수를 기억하는 함수입니다. 다른 함수 안에 도우미 함수를 정의하면 바깥 함수의 변수를 사용할 수 있어 DFS에 유용합니다.

def make_counter(start=0):
    count = [start]  # list to allow mutation
    def increment():
        count[0] += 1
        return count[0]
    return increment

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

# Alternative: nonlocal keyword
def make_counter2():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

재귀 DFS에서의 클로저

흔히 사용하는 패턴은 주 함수 안에 dfs 도우미 함수를 정의하고, 바깥 변수에 결과를 모으게 하는 것입니다. 내부 함수는 해당 범위를 포착하는 클로저입니다.

def max_depth(root):
    '''Closure pattern for tree DFS.'''
    max_d = [0]  # mutable container for closure

    def dfs(node, depth):
        if node is None:
            return
        max_d[0] = max(max_d[0], depth)
        dfs(node.left, depth + 1)
        dfs(node.right, depth + 1)

    dfs(root, 1)
    return max_d[0]
# This pattern avoids a class or global state.

메모이제이션을 위한 functools.lru_cache

lru_cache(또는 3.9 이상에서는 @cache)는 인수를 기준으로 함수의 결과를 기억하여, 단순한 피보나치 계산을 O(2^n)에서 O(n)으로 바꿉니다. 인수는 해시 가능해야 하므로 튜플을 사용하십시오.

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(40))   # 102334155  fast!
print(fib.cache_info())  # hits, misses, size

고차 함수

고차 함수는 함수를 인수로 받거나 함수로 반환합니다. sorted, map, filter가 모두 이에 해당합니다. 직접 작성하면 반복되는 패턴을 추상화할 수 있습니다. 코드에서 composition을 보여 줍니다.

def apply_twice(f, x):
    return f(f(x))

print(apply_twice(lambda n: n * 2, 3))  # 12  (3*2*2)

# Composing transformations
def compose(f, g):
    return lambda x: f(g(x))

double = lambda n: n * 2
add_one = lambda n: n + 1
double_then_add = compose(add_one, double)
print(double_then_add(5))  # 11  ((5*2)+1)

도우미 함수와 함께하는 재귀

많은 해법은 설정과 예외 상황을 처리하는 바깥 함수와 재귀를 수행하는 내부 도우미 함수를 함께 사용합니다. 공개 API는 깔끔하게 유지하고 로직은 분리할 수 있습니다. 코드를 확인해 보십시오.

def flatten(nested):
    '''Flatten an arbitrarily nested list.'''
    result = []

    def _flatten(lst):
        for item in lst:
            if isinstance(item, list):
                _flatten(item)
            else:
                result.append(item)

    _flatten(nested)
    return result

print(flatten([1, [2, [3, 4], 5], 6]))
# [1, 2, 3, 4, 5, 6]

functools.partial을 사용한 부분 함수

functools.partial은 일부 인수를 미리 채운 뒤 새로운 호출 가능 객체를 반환합니다. API가 인수 없는 함수를 요구하지만 하나의 고정된 매개변수를 지정해야 할 때 유용합니다.

from functools import partial

def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
cube   = partial(power, exp=3)

print(square(5))   # 25
print(cube(3))     # 27
print(list(map(square, [1, 2, 3, 4])))  # [1, 4, 9, 16]

사용자 지정 비교를 위한 람다

파이썬 3에서는 두 인수를 받는 비교 함수가 사라졌지만, cmp_to_key를 사용하면 까다로운 순서 지정에 다시 활용할 수 있습니다. 예를 들어 여러 수를 이어 붙였을 때 가장 큰 수가 되도록 배열할 수 있습니다. 코드를 확인해 보십시오.

from functools import cmp_to_key

def largest_number(nums):
    def compare(a, b):
        if a + b > b + a: return -1
        if a + b < b + a: return 1
        return 0
    strs = list(map(str, nums))
    strs.sort(key=cmp_to_key(compare))
    result = ''.join(strs)
    return '0' if result[0] == '0' else result

print(largest_number([3, 30, 34, 5, 9]))  # '9534330'

간단한 확인

간단히 확인해 보겠습니다. 함수, 클로저, 람다에 대해 무엇을 배웠는지 보여 줄 시간입니다. 숨을 한 번 고르고 시작하십시오. 🚀

레슨 요약

요약하면, 변경 가능한 기본값은 절대 사용하지 말고(None을 사용하십시오), 클로저를 사용하면 내부 도우미 함수가 바깥 변수에 접근할 수 있어 DFS에 활용할 수 있으며, lru_cache 같은 functools 도구로 빠른 해법을 만들 수 있습니다.

자주 묻는 질문

“함수, 클로저, 람다” 강의는 무료인가요?

네 — “함수, 클로저, 람다” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 DSA Interview Prep 강의 전체를 잠금 해제할 수 있습니다. DSA Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

“함수, 클로저, 람다”에서 뭘 배우나요?

재사용 가능한 보조 함수를 정의하고 기본 인수를 사용하며, 면접 문제의 정렬과 함수형 패턴에 람다 표현식을 적용합니다. 브라우저에서 직접 실행하는 실습 코드로 DSA Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

DSA Interview Prep을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 DSA Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“함수, 클로저, 람다” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 DSA Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 DSA Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 리스트, 튜플, 슬라이싱
  2. Python의 딕셔너리와 집합
  3. 컴프리헨션과 내장 함수
  4. 함수, 클로저, 람다
← DSA Interview Prep(으)로 돌아가기