Vasu Patel logoVasu Patel
← Python Syntax & DSA Reference
All chapters in this track
  1. 011. Variables, Types & Operators
  2. 022. Strings
  3. 033. Lists
  4. 044. Tuples, Sets & Dicts
  5. 055. Control Flow
  6. 066. Error Handling
  7. 077. Functions & Lambdas
  8. 088. Comprehensions
  9. 099. Built-in Functions
  10. 1010. Type Hints (3.10+)
  11. 1111. Classes & Dataclasses
  12. 1212. Iterators & Generators
  13. 1313. DSA Standard Library
  14. 1414. Python 3.9–3.11 Features for DSA
  15. 1515. DSA Idioms & Gotchas
  16. 1616. Master Quick Reference

Chapter 7 of 16

7. Functions & Lambdas

Tutorial

# ══ FUNCTION DEFINITION ════════════════════════════════════════
def two_sum(nums: list[int], target: int) -> list[int]:
    seen: dict[int, int] = {}
    for i, x in enumerate(nums):
        comp = target - x
        if comp in seen:
            return [seen[comp], i]
        seen[x] = i
    return []

# Default arguments
def search(arr: list[int], target: int, lo: int = 0, hi: int = -1) -> int:
    if hi == -1: hi = len(arr) - 1
    ...

# Return multiple values (returns a tuple)
def min_max(arr: list[int]) -> tuple[int, int]:
    return min(arr), max(arr)
lo, hi = min_max([3, 1, 4, 1, 5])

# ══ LAMBDAS ════════════════════════════════════════════════════
double  = lambda x: x * 2
key_fn  = lambda p: p[0]**2 + p[1]**2      # distance from origin

# Most common use: sort key
intervals.sort(key=lambda x: (x[0], -x[1]))  # by start asc, end desc
points.sort(key=lambda p: p[0] + p[1])

# ══ *ARGS / **KWARGS ═══════════════════════════════════════════
def sum_all(*args: int) -> int:
    return sum(args)

# **kwargs — variable keyword arguments → becomes a dict
def print_info(**kwargs):
    for k, v in kwargs.items():
        print(f"{k} = {v}")

print_info(name="Alice", age=30)

# Unpack into function arguments
nums = [1, 2, 3]
add(*nums)         # add(1, 2, 3)
d = {"a": 1, "b": 2, "c": 3}
add(**d)            # same as add(a=1, b=2, c=3)

# ══ NESTED FUNCTIONS & CLOSURES ═════════════════════════════════
# Alternative to nonlocal: mutate a single-element list from the closure
def diameter_v1(root):
    result = [0]          # list so the inner function can mutate it

    def dfs(node):
        if not node: return 0
        left  = dfs(node.left)
        right = dfs(node.right)
        result[0] = max(result[0], left + right)
        return 1 + max(left, right)

    dfs(root)
    return result[0]

# Python 3 alternative: nonlocal
def diameter(root):
    max_d = 0                  # outer variable

    def dfs(node) -> int:
        nonlocal max_d         # 3.x: allows mutation of outer scope var
        if not node: return 0
        l = dfs(node.left)
        r = dfs(node.right)
        max_d = max(max_d, l + r)
        return 1 + max(l, r)

    dfs(root)
    return max_d

# ══ CACHING ════════════════════════════════════════════════════
from functools import cache, lru_cache

@cache                         # 3.9+: unbounded memoize
def fib(n: int) -> int:
    if n <= 1: return n
    return fib(n-1) + fib(n-2)

@lru_cache(maxsize=None)       # equivalent to @cache (older style)
def dp(i: int, j: int) -> int: ...

fib.cache_clear()              # reset cache between test cases
fib.cache_info()               # hits, misses, maxsize, currsize

# ══ cmp_to_key ═════════════════════════════════════════════════
from functools import cmp_to_key

def cmp(a: str, b: str) -> int:
    return -1 if a+b > b+a else 1   # largest number sort

strs.sort(key=cmp_to_key(cmp))

Reference

FeatureSyntaxNotes
Type hintsdef f(x: int) -> strNot enforced; improves readability
Default paramdef f(x=0)Use None for mutable defaults
Multiple returnreturn a, bReturns tuple; unpack with a,b=f()
Lambdalambda x: exprSingle expression
Unpack argsf(*lst)
Memoize@cache3.9+, unbounded
LRU cache@lru_cache(maxsize=N)Bounded; None=unbounded
Clear cachef.cache_clear()
Outer varnonlocal xModify enclosing scope
Custom sortcmp_to_key(cmp_fn)cmp returns -1/0/1