Skip to content
Arguments and Scope
step 1/8

Reading — step 1 of 8

Learn

~3 min readFunctions

Defining a basic function is easy. Writing functions that are flexible, correct, and free of subtle bugs takes more depth. This lesson covers four critical topics: default values, keyword vs positional arguments, *args / **kwargs for variable counts, the mutable default argument trap, and scope — which variables a function can and can't see.

Positional vs keyword arguments

python

Mix carefully. Once you switch to keyword arguments in a call, all following arguments must also be keyword.

Default values

python

Defaults must come AFTER non-defaults. def f(a, b=10) ✓, def f(a=10, b) ✗.

⚠️ The mutable default argument trap

A classic Python footgun:

python

The default [] is created ONCE when the function is defined, and reused on every call. The fix:

python

Never use a mutable default (list, dict, set). Use None and create the mutable inside.

*args — variable positional arguments

python

*nums collects ALL extra positional arguments into a tuple. The name args is convention; *nums, *items, etc. are fine.

**kwargs — variable keyword arguments

python

**kwargs collects extra keyword arguments into a dict. Useful for forwarding kwargs through layers.

All four together

python

Argument unpacking — * and ** at the call site

python

You'll see this pattern constantly when forwarding arguments.

Scope — local, enclosing, global, built-in (LEGB)

When a function uses a variable, Python looks for it in this order:

  1. Local — defined inside the function.
  2. Enclosing — the surrounding (outer) function, if any.
  3. Global — top-level module variables.
  4. Built-in — names like print, len, range.
python

Modifying outer variables — global and nonlocal

Reading from outer scope is automatic. Writing requires a declaration:

python

For enclosing scope (one level out, but not module-level), use nonlocal:

python

Common mistakes

  • Mutable default arguments — see above. Bug-bait for new Pythonistas.
  • Reading global without writing — you don't need global to READ a global, only to WRITE one.
  • Confusing *args with args[0]: in the function body, args is a tuple — you index it normally.
  • Using * and ** only in definitions: they also work at call sites for unpacking.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…