c2cedge
C, Java & Python · D — Python Essentials

Python: Functions, Arguments & Comprehensions

Default arguments, *args/**kwargs, and comprehensions are everyday Python — and home to the language's single most famous gotcha.

Test weight: High (Py)Skill: Idiomatic functionsDifficulty: Medium

Python functions are flexible: default parameter values, variable positional arguments (*args), variable keyword arguments (**kwargs), and concise lambdas. Comprehensions build lists, dicts and sets in one readable line. One feature — mutable default arguments — is the most famous Python trap of all.

*args, **kwargs and comprehensions

*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dict. A list comprehension [expr for x in iterable if cond] builds a list concisely and fast — there are dict and set comprehensions too.

*args and **kwargs
def f(*args, **kwargs):
    print(args)     # a tuple of positional args
    print(kwargs)   # a dict of keyword args

f(1, 2, x=3)        # args=(1, 2)   kwargs={'x': 3}
Comprehensions
squares = [n * n for n in range(5)]          # [0, 1, 4, 9, 16]
evens   = [n for n in range(10) if n % 2 == 0] # [0, 2, 4, 6, 8]
lengths = {w: len(w) for w in ["a", "bb"]}     # {'a': 1, 'bb': 2}
⚡ The edge
  • *args becomes a tuple; **kwargs becomes a dict. They let a function accept any number of positional/keyword arguments — and you can unpack with f(*mylist, **mydict) at the call site.
  • Never use a mutable default argument like def f(x, items=[]). The list is created once when the function is defined and shared across all calls, so it accumulates. Use items=None and create a fresh list inside.
Worked example
What is the difference between *args and **kwargs?
  1. *args collects any extra positional arguments into a tuple.
  2. **kwargs collects any extra keyword (named) arguments into a dictionary.
  3. Together they let a function accept arbitrary arguments; at a call you can also unpack a list/dict with * and **.
Worked example
Why is def f(x, items=[]) dangerous?
  1. The default list is created once, when the function is defined — not on each call.
  2. Every call that relies on the default shares that same list, so appends accumulate across calls.
  3. Fix it with items=None, then 'if items is None: items = []' inside the function.
⚠ Watch out
  • Mutable default arguments are shared across calls — the classic Python bug; default to None.
  • Late binding in closures: a lambda in a loop captures the variable, not its value at creation — surprising results.
  • Comprehensions are great but don't over-nest them — readability matters.
Practice this — take a timed mock →
1,300+ questions, scored, with a weak-area report.
Know who's ready. Not who finished.
HomeLibraryPrivacyTerms