Skip to content
주제
Python
Python Lambda 함수: 실용적인 예제로 배우는 명확한 가이드

Python Lambda 함수: 실용적인 예제로 배우는 명확한 가이드

Updated on

모든 Python 프로젝트에는 작은 헬퍼 함수가 쌓여갑니다. 숫자를 두 배로 만드는 함수. 공백을 제거하는 함수. 딕셔너리에서 성을 추출하는 함수. 각각 두세 줄이고, 정확히 한 번 사용되며, 기억하지도 못할 이름으로 모듈을 어지럽힙니다. Python Lambda 함수는 필요한 바로 그 자리에 작고 일회성인 함수를 정의할 수 있게 해서 이 문제를 해결합니다 -- def 없이, 이름 없이, 낭비되는 세로 공간 없이.

📚

이 가이드는 Python Lambda 함수에 대해 알아야 할 모든 것을 다룹니다: 문법, 함께 사용되는 내장 함수, 실제 코드를 위한 실용적인 패턴, 그리고 피해야 할 구체적인 상황들.

Lambda 함수란?

Lambda 함수는 익명의 단일 표현식 함수입니다. "익명"이란 이름이 없다는 뜻입니다. "단일 표현식"이란 함수 본체가 정확히 하나의 표현식이며 그 결과가 자동으로 반환된다는 뜻입니다. Python은 그 표현식을 평가하고 결과를 돌려줍니다 -- return 문이 필요 없습니다.

이 용어는 수리논리학의 형식 체계인 람다 대수에서 유래합니다. 하지만 수학을 이해할 필요는 없습니다. 실용적인 Python에서 lambda는 단순히 작은 함수를 작성하는 더 짧은 방법입니다.

다음은 일반 함수와 그에 해당하는 lambda입니다:

# Regular function
def double(x):
    return x * 2
 
print(double(5))
# 10
 
# Lambda equivalent
double_lambda = lambda x: x * 2
 
print(double_lambda(5))
# 10

둘 다 같은 결과를 생성합니다. Lambda 버전은 한 줄에 들어가며 defreturn의 형식을 생략합니다.

Lambda 문법

Python Lambda의 문법은 다음과 같습니다:

lambda arguments: expression
  • lambda -- 익명 함수를 나타내는 키워드.
  • arguments -- 쉼표로 구분된 0개 이상의 매개변수. 괄호 불필요.
  • expression -- 평가되어 반환되는 단일 표현식. 문(statement)은 불가 (if 블록, for 루프, =를 사용한 할당 불가).

범위를 보여주는 몇 가지 빠른 예제:

# No arguments
greet = lambda: "Hello, world!"
print(greet())
# Hello, world!
 
# One argument
square = lambda x: x ** 2
print(square(9))
# 81
 
# Two arguments
add = lambda a, b: a + b
print(add(3, 7))
# 10
 
# Default argument
power = lambda base, exp=2: base ** exp
print(power(3))
# 9
print(power(3, 3))
# 27

핵심 제약은 본체가 단일 표현식이어야 한다는 것입니다. 여러 줄의 로직을 작성하거나, if 문을 사용하거나 (조건 표현식은 사용 가능), 할당을 포함할 수 없습니다. 이것은 의도적입니다 -- lambda는 간단한 연산을 위해 설계되었습니다.

Lambda와 map() -- 리스트 변환

map()은 이터러블의 각 요소에 함수를 적용하고 이터레이터를 반환합니다. 변환이 한 줄로 표현할 수 있을 만큼 간단한 경우가 많기 때문에, Lambda 함수는 map()의 자연스러운 동반자입니다.

numbers = [1, 2, 3, 4, 5]
 
# Square each number
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
# [1, 4, 9, 16, 25]
 
# Convert temperatures from Celsius to Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print(fahrenheit)
# [32.0, 68.0, 98.6, 212.0]
 
# Extract first names from full names
names = ["Ada Lovelace", "Grace Hopper", "Alan Turing"]
first_names = list(map(lambda name: name.split()[0], names))
print(first_names)
# ['Ada', 'Grace', 'Alan']

map()과 lambda의 조합은 매핑 로직이 간단한 한 단계 변환일 때 리스트 컴프리헨션의 깔끔한 대안입니다. 더 복잡한 변환의 경우, 리스트 컴프리헨션이 더 읽기 쉬운 경향이 있습니다.

Lambda와 filter() -- 요소 필터링

filter()는 함수와 이터러블을 받아, 함수가 True를 반환하는 요소만 생성하는 이터레이터를 반환합니다. Lambda 함수는 조건을 인라인으로 쉽게 정의할 수 있게 합니다.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
# Keep only even numbers
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)
# [2, 4, 6, 8, 10]
 
# Keep strings longer than 4 characters
words = ["cat", "elephant", "dog", "butterfly", "ant"]
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words)
# ['elephant', 'butterfly']
 
# Filter out None values
data = [1, None, 3, None, 5, None, 7]
clean = list(filter(lambda x: x is not None, data))
print(clean)
# [1, 3, 5, 7]

map()과 마찬가지로, filter() + lambda 조합은 간단한 조건에 가장 잘 작동합니다. 필터링 로직에 여러 검사가 포함되는 경우, 리스트 컴프리헨션이나 이름이 있는 함수가 보통 더 명확합니다.

Lambda와 sorted() 및 sort() -- 사용자 정의 정렬 키

정렬은 Lambda 함수의 가장 일반적이고 실용적인 용도 중 하나입니다. sorted() 함수와 .sort() 메서드는 모두 key 매개변수를 받습니다 -- 각 요소에서 비교 값을 추출하는 함수입니다.

# Sort strings by length
fruits = ["banana", "kiwi", "strawberry", "fig", "apple"]
by_length = sorted(fruits, key=lambda s: len(s))
print(by_length)
# ['fig', 'kiwi', 'apple', 'banana', 'strawberry']
 
# Sort tuples by the second element
pairs = [(1, 'b'), (3, 'a'), (2, 'c')]
by_second = sorted(pairs, key=lambda pair: pair[1])
print(by_second)
# [(3, 'a'), (1, 'b'), (2, 'c')]
 
# Sort dictionaries by a specific key
students = [
    {"name": "Alice", "grade": 88},
    {"name": "Bob", "grade": 95},
    {"name": "Charlie", "grade": 72},
]
by_grade = sorted(students, key=lambda s: s["grade"], reverse=True)
for s in by_grade:
    print(f"{s['name']}: {s['grade']}")
# Bob: 95
# Alice: 88
# Charlie: 72

lambda를 사용한 정렬은 너무 널리 사용되어 Python의 관용적 패턴이 되었습니다. 특정 속성이나 필드로 복잡한 객체를 정렬해야 할 때마다, lambda 키 함수가 표준 접근법입니다.

여러 기준으로 정렬

lambda에서 튜플을 반환하여 여러 필드로 정렬할 수 있습니다:

employees = [
    {"name": "Alice", "dept": "Engineering", "salary": 95000},
    {"name": "Bob", "dept": "Marketing", "salary": 72000},
    {"name": "Charlie", "dept": "Engineering", "salary": 88000},
    {"name": "Diana", "dept": "Marketing", "salary": 85000},
]
 
# Sort by department (ascending), then by salary (descending)
sorted_emp = sorted(employees, key=lambda e: (e["dept"], -e["salary"]))
for e in sorted_emp:
    print(f"{e['dept']:12s} {e['name']:8s} ${e['salary']:,}")
# Engineering  Alice    $95,000
# Engineering  Charlie  $88,000
# Marketing    Diana    $85,000
# Marketing    Bob      $72,000

Lambda와 functools의 reduce()

functools.reduce()는 두 인수를 받는 함수를 이터러블의 요소에 누적적으로 적용하여 단일 값으로 축소합니다. Lambda 함수는 간결한 집계를 위해 reduce()와 자연스럽게 결합됩니다.

from functools import reduce
 
numbers = [1, 2, 3, 4, 5]
 
# Product of all numbers
product = reduce(lambda x, y: x * y, numbers)
print(product)
# 120
 
# Find the maximum value (for demonstration; use max() in practice)
largest = reduce(lambda a, b: a if a > b else b, numbers)
print(largest)
# 5
 
# Concatenate a list of strings
words = ["Python", " ", "lambda", " ", "functions"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence)
# Python lambda functions
 
# Flatten a list of lists
nested = [[1, 2], [3, 4], [5, 6]]
flat = reduce(lambda acc, lst: acc + lst, nested)
print(flat)
# [1, 2, 3, 4, 5, 6]

주의사항: reduce()는 의도를 모호하게 만들 수 있습니다. 합산과 같은 일반적인 연산에는 sum()을 사용하세요. 최솟값/최댓값을 찾으려면 min()max()를 사용하세요. 내장 함수가 없는 사용자 정의 누적에만 reduce()와 lambda를 사용하세요.

Lambda vs def -- 각각 언제 사용할 것인가

이것이 실무에서 가장 중요한 질문입니다. Lambda와 def는 모두 함수 객체를 생성하지만, 서로 다른 목적을 가지고 있습니다.

특성lambdadef
이름익명 (이름 없음)이름 있는 함수
본체단일 표현식만여러 문, 루프, 조건
반환암시적 (표현식 결과)명시적 return
Docstring미지원지원
타입 힌트미지원지원
디버깅트레이스백에 <lambda> 표시트레이스백에 함수 이름 표시
가독성간단하고 짧은 연산에 최적다단계 작업에 최적
테스트 용이성단독 테스트 어려움이름으로 유닛 테스트 용이
재사용일반적으로 일회성, 인라인재사용을 위해 설계
데코레이터@decorator 문법 사용 불가완전한 데코레이터 지원

Lambda를 사용해야 할 때

  • 정렬 키: sorted(items, key=lambda x: x.name)
  • 빠른 map/filter 연산: map(lambda x: x.strip(), lines)
  • 콜백 인수: 호출 가능한 매개변수를 받는 함수
  • 간단한 딕셔너리 또는 튜플 접근: key=lambda item: item[1]

def를 사용해야 할 때

  • 함수에 하나 이상의 표현식이 있는 경우
  • docstring이나 타입 힌트가 필요한 경우
  • 함수가 여러 곳에서 호출되는 경우
  • 로직에 에러 처리나 분기가 필요한 경우
  • 디버깅을 위해 스택 트레이스에 의미 있는 이름이 필요한 경우

경험 법칙: lambda가 한 줄에 편안하게 들어가지 않거나, 무엇을 하는지 이해하기 위해 두 번 읽어야 한다면, 대신 def를 사용하세요.

여러 인수를 가진 Lambda

Lambda 함수는 *args**kwargs를 포함하여 임의의 수의 인수를 받을 수 있습니다:

# Three arguments
volume = lambda l, w, h: l * w * h
print(volume(3, 4, 5))
# 60
 
# Using *args for variable arguments
sum_all = lambda *args: sum(args)
print(sum_all(1, 2, 3, 4, 5))
# 15
 
# Using **kwargs
build_greeting = lambda **kwargs: f"Hello, {kwargs.get('name', 'stranger')}!"
print(build_greeting(name="Alice"))
# Hello, Alice!
print(build_greeting())
# Hello, stranger!
 
# Conditional expression inside lambda
classify = lambda x: "positive" if x > 0 else ("zero" if x == 0 else "negative")
print(classify(5))
# positive
print(classify(0))
# zero
print(classify(-3))
# negative

마지막 예제의 조건 표현식(a if condition else b)에 주목하세요. 이것이 lambda 안에 분기 로직을 추가하는 유일한 방법입니다. 작동하지만, 여러 조건을 중첩하면 가독성이 빠르게 떨어집니다.

딕셔너리 연산에서의 Lambda

Lambda 함수는 딕셔너리 데이터의 변환과 정렬에 유용합니다:

# Sort a dictionary by value
scores = {"Alice": 88, "Bob": 95, "Charlie": 72, "Diana": 91}
sorted_scores = dict(sorted(scores.items(), key=lambda item: item[1], reverse=True))
print(sorted_scores)
# {'Bob': 95, 'Diana': 91, 'Alice': 88, 'Charlie': 72}
 
# Apply a transformation to all dictionary values
prices = {"apple": 1.20, "banana": 0.50, "cherry": 2.00}
discounted = {k: round(v * 0.9, 2) for k, v in prices.items()}
print(discounted)
# {'apple': 1.08, 'banana': 0.45, 'cherry': 1.8}
 
# Group items using a lambda as a key function
from itertools import groupby
 
data = ["apple", "avocado", "banana", "blueberry", "cherry", "cranberry"]
data_sorted = sorted(data, key=lambda x: x[0])
 
for letter, group in groupby(data_sorted, key=lambda x: x[0]):
    print(f"{letter}: {list(group)}")
# a: ['apple', 'avocado']
# b: ['banana', 'blueberry']
# c: ['cherry', 'cranberry']

Lambda와 Pandas: df.apply()와 df.sort_values()

Lambda 함수는 pandas에서 행 수준 변환과 사용자 정의 정렬에 많이 사용됩니다. apply() 메서드는 DataFrame의 각 행 또는 열에 함수를 실행하며, lambda는 코드를 인라인으로 유지합니다.

import pandas as pd
 
df = pd.DataFrame({
    "name": ["Alice", "Bob", "Charlie", "Diana"],
    "score": [88, 95, 72, 91],
    "department": ["Engineering", "Marketing", "Engineering", "Marketing"]
})
 
# Add a new column with a grade label
df["grade"] = df["score"].apply(lambda x: "A" if x >= 90 else ("B" if x >= 80 else "C"))
print(df)
#       name  score   department grade
# 0    Alice     88  Engineering     B
# 1      Bob     95    Marketing     A
# 2  Charlie     72  Engineering     C
# 3    Diana     91    Marketing     A

sort_values(key=)에서 Lambda 사용

sort_values()key 매개변수는 정렬 전에 열에 적용되는 함수를 받습니다:

import pandas as pd
 
df = pd.DataFrame({
    "product": ["Widget A", "Widget B", "Widget C"],
    "price": ["$29.99", "$9.50", "$149.00"]
})
 
# Sort by numeric price value (strip the $ sign first)
df_sorted = df.sort_values("price", key=lambda col: col.str.replace("$", "", regex=False).astype(float))
print(df_sorted)
#     product    price
# 1  Widget B    $9.50
# 0  Widget A   $29.99
# 2  Widget C  $149.00

apply()를 행 방향으로 Lambda 사용

각 행에 lambda를 적용하려면 axis=1을 설정합니다:

import pandas as pd
 
df = pd.DataFrame({
    "first_name": ["Ada", "Grace", "Alan"],
    "last_name": ["Lovelace", "Hopper", "Turing"],
    "birth_year": [1815, 1906, 1912]
})
 
# Create a full name column
df["full_name"] = df.apply(lambda row: f"{row['first_name']} {row['last_name']}", axis=1)
 
# Calculate age (approximate, as of 2026)
df["approx_age"] = df["birth_year"].apply(lambda y: 2026 - y)
 
print(df)
#   first_name last_name  birth_year       full_name  approx_age
# 0        Ada  Lovelace        1815  Ada Lovelace          211
# 1      Grace    Hopper        1906  Grace Hopper          120
# 2       Alan    Turing        1912    Alan Turing          114

일반적인 Lambda 패턴과 관용구

다음은 프로덕션 Python 코드에서 자주 접하게 될 패턴입니다:

# 1. Default factory for collections.defaultdict
from collections import defaultdict
 
word_count = defaultdict(lambda: 0)
for word in ["apple", "banana", "apple", "cherry", "banana", "apple"]:
    word_count[word] += 1
print(dict(word_count))
# {'apple': 3, 'banana': 2, 'cherry': 1}
 
# 2. Immediate invocation (IIFE - Immediately Invoked Function Expression)
result = (lambda x, y: x + y)(3, 4)
print(result)
# 7
 
# 3. Lambda as a callback in GUI or event-driven code
# button.on_click(lambda event: print(f"Clicked at {event.x}, {event.y}"))
 
# 4. Using lambda with min/max for custom comparisons
products = [
    ("Laptop", 999),
    ("Mouse", 25),
    ("Keyboard", 75),
    ("Monitor", 450),
]
cheapest = min(products, key=lambda p: p[1])
print(cheapest)
# ('Mouse', 25)
 
# 5. Lambda with conditional expression for data cleaning
clean = lambda s: s.strip().lower() if isinstance(s, str) else s
print(clean("  Hello World  "))
# hello world
print(clean(42))
# 42

Lambda를 사용하지 말아야 할 때

Lambda 함수에는 명확한 한계가 있습니다. 이 한계를 넘어서 사용하면 읽기 어렵고, 디버그하기 어렵고, 유지보수하기 어려운 코드가 됩니다.

다음의 경우 lambda를 피하세요:

  1. 로직이 복잡한 경우. 중첩된 조건, 여러 연산, 또는 어떤 형태의 에러 처리가 필요하면 def를 사용하세요.
# Bad -- hard to read
process = lambda x: x.strip().lower().replace(" ", "_") if isinstance(x, str) and len(x) > 0 else "empty"
 
# Good -- clear and testable
def process(x):
    """Normalize a string to a snake_case identifier."""
    if not isinstance(x, str) or len(x) == 0:
        return "empty"
    return x.strip().lower().replace(" ", "_")
 
print(process("  Hello World  "))
# hello_world
  1. 재사용을 위해 lambda를 변수에 할당하는 경우. PEP 8은 lambda에 이름을 할당하는 대신 def를 사용할 것을 명시적으로 권장합니다. 함수가 이름을 가질 자격이 있다면, 적절한 정의를 주세요.

  2. docstring이나 타입 힌트가 필요한 경우. Lambda 함수는 둘 다 지원하지 않습니다. 이름 있는 함수는 지원합니다.

  3. 디버깅이 중요한 경우. Lambda 함수는 트레이스백에서 <lambda>로 표시되므로, 여러 개의 lambda가 있을 때 어떤 lambda가 에러를 일으켰는지 식별하기 어렵습니다.

  4. 가독성이 저하되는 경우. 동료가 lambda를 이해하는 데 3초 이상 걸린다면, 이름 있는 함수로 다시 작성하세요.

상황lambda 사용def 사용
sorted()의 정렬 키복잡한 경우에만
빠른 map()/filter()다단계인 경우
여러 곳에서 재사용아니오
복잡한 분기아니오
docstring 필요아니오
API에서 콜백로직이 커지는 경우
에러 처리 필요아니오

RunCell로 Lambda 함수 작성 및 리팩토링

Jupyter 노트북에서 Lambda 함수를 사용하는 것은 데이터 사이언스 워크플로에서 흔한 일입니다. 복잡한 pandas apply() 호출을 작성하거나 여러 map()filter() 연산을 체이닝할 때, lambda가 올바른 도구인지 아니면 이름 있는 함수로 리팩토링해야 하는지 판단하기 어려울 수 있습니다.

RunCell (opens in a new tab)은 Jupyter 노트북 내에서 직접 작동하도록 설계된 AI 에이전트입니다. 노트북 컨텍스트 -- 메모리에 있는 변수, 작업 중인 DataFrame, 로드된 import -- 를 이해하고 정확한 제안을 제공합니다.

RunCell이 Lambda 함수에 특별히 도움이 되는 방법:

  • Lambda에서 def로 리팩토링. Lambda가 너무 길어지면, RunCell은 정확한 동작을 유지하면서 타입 힌트와 docstring이 포함된 깔끔한 def 버전을 제안할 수 있습니다.
  • 성능 힌트. 큰 DataFrame에서 df.apply(lambda ...)를 사용하고 있다면, RunCell은 10~100배 빠른 네이티브 pandas 또는 NumPy 연산을 사용한 벡터화된 대안을 제안할 수 있습니다.
  • 인라인 설명. 중첩된 lambda로 가득한 다른 사람의 코드를 다루고 있나요? RunCell은 노트북에서 각 lambda가 무엇을 하는지 쉬운 말로 분석해줄 수 있습니다.
  • 패턴 제안. 원하는 것을 설명하세요 -- "이 딕셔너리 리스트를 날짜로 정렬하고, 그 다음 이름으로 정렬" -- RunCell이 올바른 lambda 키 함수가 포함된 올바른 sorted() 호출을 생성합니다.

RunCell은 기존 Jupyter 환경 내에서 실행되므로, 컨텍스트 전환이 없습니다. 노트북에 머물면서 AI 에이전트가 함께 작업합니다.

FAQ

Python에서 Lambda 함수란 무엇인가요?

Lambda 함수는 lambda 키워드로 정의되는 작고 익명인 함수입니다. 임의의 수의 인수를 받을 수 있지만, 단일 표현식만 포함할 수 있습니다. 표현식의 결과는 자동으로 반환됩니다. Lambda 함수는 일반적으로 정렬 키, map/filter 콜백, 인라인 변환과 같은 짧고 일회성인 연산에 사용됩니다.

Python Lambda는 여러 줄을 가질 수 있나요?

아니오. Python Lambda는 단일 표현식으로 제한됩니다. lambda 안에서 여러 문, 루프, 할당을 사용할 수 없습니다. 여러 줄의 로직이 필요하면 일반 def 함수를 사용하세요. 하지만 간단한 분기를 위해 lambda 안에서 조건 표현식(a if condition else b)을 사용할 수 있습니다.

Python에서 lambda와 def의 차이점은 무엇인가요?

둘 다 함수 객체를 생성하지만 범위가 다릅니다: lambda는 인라인으로 사용되는 익명의 단일 표현식 함수를 생성하고, def는 여러 문, docstring, 타입 힌트, 데코레이터를 포함할 수 있는 이름 있는 함수를 생성합니다. 간단한 일회성 연산에는 lambda를, 이름, 문서화, 복잡한 로직이 필요한 것에는 def를 사용하세요.

리스트 컴프리헨션 대신 Lambda를 언제 사용해야 하나요?

연산이 간단한 단일 변환이나 조건인 경우 map()이나 filter()와 lambda를 사용하세요. 한 단계에서 필터링과 변환이 모두 필요하거나, 로직이 [expr for x in iterable if condition] 구조의 이점을 받는 경우 리스트 컴프리헨션을 사용하세요. 현대 Python에서는 가독성 때문에 리스트 컴프리헨션이 일반적으로 선호되지만, lambda는 정렬 키와 콜백 매개변수의 표준입니다.

Python Lambda 함수는 느린가요?

아니오. Lambda 함수는 동등한 def 함수와 같은 성능을 가집니다. 둘 중 하나를 호출하는 오버헤드는 동일합니다. 하지만 pandas에서 df.apply(lambda ...)를 사용하는 것은 벡터화된 연산에 비해 느립니다. 병목은 행별 Python 실행이지, lambda 자체가 아닙니다. 가능하면, 더 나은 성능을 위해 apply(lambda ...)를 내장 pandas 또는 NumPy 메서드로 대체하세요.

결론

Python Lambda 함수는 특정 틈새를 채웁니다: 필요한 곳에 정확히 정의하는 짧은 익명 함수입니다. 정렬 키, map()/filter() 콜백, 인라인 변환으로 사용할 때 가장 좋습니다. sorted(), map(), filter(), reduce(), pandas apply()와 자연스럽게 결합됩니다.

잘 사용하기 위한 규칙은 간단합니다:

  • 하나의 간단한 표현식으로 유지하세요.
  • 인라인으로 사용하고, 변수에 할당하지 마세요 (PEP 8 가이드라인).
  • 로직이 읽기 어려워지는 순간 def로 전환하세요.
  • pandas에서는 성능을 위해 apply(lambda ...)보다 벡터화된 연산을 선호하세요.
  • 조건 표현식은 아껴서 사용하세요 -- lambda 안의 중첩된 삼항 연산자는 가독성의 함정입니다.

Lambda는 도구이지, 영리함의 배지가 아닙니다. 최고의 Python 코드는 단순화하는 곳에서 lambda를 사용하고, 명확히 하는 곳에서 def를 사용합니다. 이 둘의 경계를 아는 것이 읽기 좋은 코드와 미래의 자신(또는 팀원)을 고생시키는 코드를 구분하는 것입니다.

📚