Python Cheatsheet
Functions
Use this Python reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Defining Functions
def greet(name): """Return a greeting string.""" return f"Hello, {name}!" # No return value returns None implicitly def side_effect(x): print(x) # Call result = greet("Alice")
Parameters and Arguments
# Positional def add(a, b): return a + b add(1, 2) # positional add(b=2, a=1) # keyword (any order) # Default values — mutable defaults are a common bug! def append_to(item, lst=None): # correct if lst is None: lst = [] lst.append(item) return lst # BAD: def append_to(item, lst=[]): # lst shared across calls # Positional-only (Python 3.8+, before /) def pos_only(a, b, /, c): pass # pos_only(1, 2, 3) — a and b must be positional # Keyword-only (after *) def kw_only(a, *, b, c=10): pass # kw_only(1, b=2) — b must be keyword # Both def mixed(pos_only, /, normal, *, kw_only): pass
args and *kwargs
# *args — variable positional arguments (tuple) def total(*nums): return sum(nums) total(1, 2, 3, 4) # 10 # **kwargs — variable keyword arguments (dict) def info(**kw): for k, v in kw.items(): print(f"{k}: {v}") info(name="Alice", age=30) # Combined signature (order matters) def func(a, b, *args, key=None, **kwargs): pass # Unpacking when calling lst = [1, 2, 3] dct = {"key": "val"} func(*lst) # unpack list as positional args func(**dct) # unpack dict as keyword args func(*lst, **dct)
Return Values
def nothing(): return # returns None # or just fall off the end def single(): return 42 def multiple(): return 1, 2, 3 # returns tuple (1, 2, 3) a, b, c = multiple() # unpacking
Lambda Functions
Anonymous single-expression functions.
square = lambda x: x ** 2 square(5) # 25 add = lambda a, b: a + b add(3, 4) # 7 # Common use: key for sort/min/max pairs = [(1, "b"), (2, "a")] pairs.sort(key=lambda p: p[1]) # sort by second element min(words, key=lambda w: len(w)) # shortest word sorted(data, key=lambda x: -x) # descending # Lambda with default fn = lambda x, n=2: x ** n
Closures
def make_counter(start=0): count = start def counter(): nonlocal count count += 1 return count return counter c = make_counter() c() # 1 c() # 2 # Closure captures variable by reference (gotcha in loops!) fns = [] for i in range(3): fns.append(lambda x, i=i: x + i) # default arg captures current i
Decorators
import functools def my_decorator(func): @functools.wraps(func) # preserve __name__, __doc__ def wrapper(*args, **kwargs): print("before") result = func(*args, **kwargs) print("after") return result return wrapper @my_decorator def greet(name): print(f"Hi {name}") # Equivalent to: greet = my_decorator(greet)
See the Decorators cheatsheet for full coverage.
Type Hints
def add(a: int, b: int) -> int: return a + b def greet(name: str = "World") -> str: return f"Hello, {name}!" # Complex types (Python 3.9+ built-ins; or import from typing) def process(items: list[int]) -> dict[str, int]: return {"sum": sum(items)} from typing import Optional, Union, Callable, Any, TypeVar def find(lst: list[int], val: int) -> Optional[int]: ... def either(x: Union[int, str]) -> str: return str(x) # Python 3.10+ union shorthand def fn(x: int | str | None) -> None: pass T = TypeVar("T") def identity(x: T) -> T: return x
Generators
def count_up(n): for i in range(n): yield i gen = count_up(5) next(gen) # 0 next(gen) # 1 list(gen) # [2, 3, 4] # yield from — delegate to sub-generator def flatten(lst): for item in lst: if isinstance(item, list): yield from flatten(item) else: yield item # Generator expression (no function needed) gen = (x ** 2 for x in range(10)) sum(x ** 2 for x in range(10)) # 285 # send() — two-way communication def accumulator(): total = 0 while True: value = yield total if value is None: break total += value acc = accumulator() next(acc) # prime the generator acc.send(10) # 10 acc.send(20) # 30
Higher-Order Functions
# map — apply function to each element list(map(str, [1, 2, 3])) # ['1', '2', '3'] list(map(lambda x: x*2, range(5))) # [0, 2, 4, 6, 8] # filter — keep elements where function returns True list(filter(None, [0, 1, "", "a"])) # [1, 'a'] (None = identity) list(filter(lambda x: x > 0, [-1, 0, 1, 2])) # [1, 2] # reduce from functools import reduce reduce(lambda acc, x: acc + x, [1, 2, 3, 4]) # 10 # sorted with key sorted(["banana", "apple", "cherry"], key=len) # by length sorted(data, key=lambda x: (x.priority, x.name)) # multi-key # Partial application from functools import partial double = partial(pow, exp=2) # won't work due to keyword; typical use: add5 = partial(lambda a, b: a + b, 5) add5(3) # 8
functools Essentials
from functools import wraps, lru_cache, cache, reduce, partial, total_ordering # Memoization @lru_cache(maxsize=128) def fib(n): if n < 2: return n return fib(n-1) + fib(n-2) fib.cache_info() # CacheInfo(hits=..., misses=..., ...) fib.cache_clear() @cache # unbounded cache (Python 3.9+) def expensive(n): ... # total_ordering — define __eq__ + one of lt/le/gt/ge, get the rest @total_ordering class Weight: def __init__(self, kg): self.kg = kg def __eq__(self, other): return self.kg == other.kg def __lt__(self, other): return self.kg < other.kg
Recursion
import sys sys.getrecursionlimit() # default 1000 sys.setrecursionlimit(5000) # increase if needed def factorial(n): if n <= 1: return 1 return n * factorial(n - 1) # Tail-call style (Python doesn't optimize tail calls, but readable) def factorial(n, acc=1): if n <= 1: return acc return factorial(n - 1, acc * n)
Introspection
import inspect inspect.signature(func) # Signature object inspect.getfullargspec(func) # args, varargs, varkw, defaults inspect.getsource(func) # source code as string inspect.isfunction(obj) # True for def-defined functions inspect.ismethod(obj) # True for bound methods inspect.isbuiltin(obj) # True for built-in functions func.__name__ # "func" func.__doc__ # docstring func.__annotations__ # type hints dict func.__defaults__ # tuple of default values func.__code__.co_varnames # local variable names