Lambda в Python: шпаргалка для аналитика

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

Синтаксис

lambda arguments: expression

Lambda — это анонимная функция из одного выражения. Эквивалент:

def f(x):
    return x * 2
# ==
f = lambda x: x * 2

Когда использовать lambda

  • Короткая функция, которая нужна один раз
  • Передать функцию как аргумент (map, filter, sorted, apply, groupby)
  • Короткий key для сортировки / сравнения

Когда НЕ использовать: если функция длиннее одной строки или используется несколько раз — пишите def.

1. map()

nums = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, nums))
# [1, 4, 9, 16]

2. filter()

nums = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, nums))
# [2, 4, 6]

3. sorted() с ключом

users = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
]

sorted_users = sorted(users, key=lambda u: u['age'])
# сначала Bob, потом Alice

Обратная сортировка:

sorted(users, key=lambda u: u['age'], reverse=True)

Сортировка по нескольким ключам (кортеж):

sorted(users, key=lambda u: (u['age'], u['name']))

4. max / min с ключом

products = [{'name': 'A', 'price': 100}, {'name': 'B', 'price': 200}]

most_expensive = max(products, key=lambda p: p['price'])
# {'name': 'B', 'price': 200}

5. reduce()

from functools import reduce

nums = [1, 2, 3, 4, 5]
total = reduce(lambda a, b: a + b, nums)
# 15

6. pandas apply

import pandas as pd

df = pd.DataFrame({'price': [100, 200, 300], 'qty': [2, 3, 1]})

df['total'] = df.apply(lambda row: row['price'] * row['qty'], axis=1)

На серии:

df['price_rub'] = df['price_usd'].apply(lambda x: x * 90)

7. pandas groupby + agg / transform

# среднее отклонение от группы
df['diff_from_group'] = df.groupby('category')['value'].transform(
    lambda x: x - x.mean()
)

# агрегация с lambda
df.groupby('category')['value'].agg(lambda x: x.quantile(0.95))

8. Словарь с default-функцией (defaultdict)

from collections import defaultdict

d = defaultdict(lambda: 'неизвестно')
d['a'] = 'яблоко'
print(d['b'])  # 'неизвестно'

9. Sorting в classes

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

products = [Product('A', 100), Product('B', 50)]
sorted_products = sorted(products, key=lambda p: p.price)

10. Условное выражение в lambda

Тернарный if:

classify = lambda x: 'big' if x > 100 else 'small'

classify(150)  # 'big'
classify(50)   # 'small'

Несколько условий через цепочку:

grade = lambda x: 'A' if x >= 90 else 'B' if x >= 75 else 'C' if x >= 60 else 'F'

(Но для такого лучше def с if/elif.)

Частые ошибки

Ошибка 1: lambda в цикле (closure issue)

# все функции в списке вернут 4 (последнее значение i)
funcs = [lambda: i for i in range(5)]
print([f() for f in funcs])  # [4, 4, 4, 4, 4]

Правильно — захватить i:

funcs = [lambda i=i: i for i in range(5)]
print([f() for f in funcs])  # [0, 1, 2, 3, 4]

Ошибка 2: Слишком длинная lambda

# плохо
lambda row: row['price'] * row['qty'] if row['status'] == 'paid' else 0 if row['refunded'] else row['price']

# хорошо — обычная функция
def total_amount(row):
    if row['status'] == 'paid':
        return row['price'] * row['qty']
    elif row['refunded']:
        return 0
    return row['price']

Ошибка 3: lambda для именованной логики

# плохо
is_premium = lambda user: user.subscription == 'premium'

# хорошо
def is_premium(user):
    return user.subscription == 'premium'

Ошибка 4: lambda вместо itemgetter / attrgetter

from operator import itemgetter, attrgetter

# работает, но медленнее
sorted(users, key=lambda u: u['age'])

# быстрее и яснее
sorted(users, key=itemgetter('age'))

Производительность

  • lambda не быстрее обычных функций (вызов то же самое)
  • Для горячего кода: itemgetter, attrgetter, list comprehensions часто быстрее
  • NumPy: vectorized операции >>> lambda в apply

Связанные темы

FAQ

Чем lambda отличается от обычной функции?

lambda — анонимная, только одно выражение, возвращает результат автоматически. def — именованная, может содержать много строк, явный return.

Можно ли в lambda использовать if/else?

Только тернарный: lambda x: a if condition else b. Обычный if на несколько строк — нельзя.

Почему lambda считают плохим стилем?

Не плохим, а неуместным в 70% случаев. В map/filter/sorted/apply — отлично. Как замена def — хуже читаемость.

Можно ли рекурсию в lambda?

Технически да через self = lambda x: ... self(x-1) ..., но практически — нет, используйте def.


Тренируйте Python для собесов — откройте тренажёр с 1500+ вопросами для аналитиков.