Python Essentials for AI Engineer

Course Content

Python Essentials for AI Engineer

6 sections · 48 lessons

What is a lambda function?


What you need to know

Syntax

Python
square = lambda x: x ** 2              # works, but PEP 8 says use def for named functionsdef square_def(x): return x ** 2print(square(4), square_def(4))        # 16 16label = lambda p: "fraud" if p > 0.8 else "ok"   # a conditional EXPRESSION is allowedprint(label(0.93), label(0.2))         # fraud ok

lambda params: expression — no return keyword, no statements like if blocks, for loops, try or assignments. The value of the expression is returned.

Where lambdas fit

Their natural home is as a key function. sorted, min, max and many pandas methods call it once per item to get the value to compare:

Python
results = [    {"doc": "refund-policy", "score": 0.82},    {"doc": "kyc-guide", "score": 0.47},    {"doc": "upi-limits", "score": 0.91},]top2 = sorted(results, key=lambda r: r["score"], reverse=True)[:2]print([r["doc"] for r in top2])        # ['upi-limits', 'refund-policy']

For simple field access, operator.itemgetter("score") does the same job.

map and filter vs comprehensions

list(map(lambda x: x * 2, nums)) works, but [x * 2 for x in nums] is shorter and clearer. Most Python style guides prefer comprehensions.

The late-binding trap

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

A lambda looks up i when it is called, not when it is created, so all three see the final value. Binding it as a default argument captures the value at creation time. This applies to def inside loops too.

A real-life example

You benchmark three LLMs on 200 support tickets and need to choose one:

Python
models = [    {"name": "model-a", "accuracy": 0.91, "p95_ms": 1800, "cost_per_1k": 0.60},    {"name": "model-b", "accuracy": 0.89, "p95_ms": 650,  "cost_per_1k": 0.15},    {"name": "model-c", "accuracy": 0.84, "p95_ms": 400,  "cost_per_1k": 0.05},]fast_enough = [m for m in models if m["p95_ms"] <= 1000]best = max(fast_enough, key=lambda m: m["accuracy"])print(best["name"])       # model-bcheapest = min(models, key=lambda m: (m["cost_per_1k"], -m["accuracy"]))print(cheapest["name"])   # model-c

Each lambda is a one-line rule used once, so a named function would add noise. If the selection rule grew into a weighted score with budget checks, it would become a def score_model(m) with a docstring and a unit test.

Follow-up questions to expect

  • "Can a lambda have multiple statements?" — No. One expression only. A conditional expression (a if cond else b) is allowed.
  • "Is a lambda faster than a def?" — No. Both compile to the same kind of function object; the difference is only syntax.
  • "What is the late-binding problem?" — Lambdas created in a loop all see the loop variable's final value; fix it with a default argument like lambda i=i: ....