CHAPTER 15 · BEGINNER4 min read

Parameters and scope

Pass arguments clearly, understand local names, and avoid accidental sharing through defaults.

Python 3.12+Free to readModule 4 of 13
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Use positional and keyword arguments with sensible default values.
  • Distinguish a local name assignment from a caller-visible mutation.
  • Avoid shared mutable defaults with a None sentinel.

01Match arguments to parameters deliberately

A parameter is a name in a function definition; an argument is a value supplied in a call. Positional arguments bind in order. Keyword arguments name the parameter explicitly, which helps when several arguments have similar types or meanings. Once you start supplying ordinary keyword arguments, do not follow them with ordinary positional arguments. A parameter also cannot receive a value twice in the same call.

Defaults make selected parameters optional. Put required parameters before parameters with defaults in these ordinary definitions. In the example, quantity defaults to one, but callers can override it. Keyword calls can change the order in which named arguments appear without changing their meaning. Prefer calls that a reader can interpret without jumping back to the definition, especially for boolean settings or several numeric options.

argument_styles.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

02A local assignment does not rebind the caller

A function's local scope contains its parameters and names assigned inside the body. Assigning to a parameter binds that local name to a new value; it does not reassign the caller's variable. In the next example, increasing count produces a local result, while the caller's count stays five. Returning the new value gives the caller an explicit way to use it.

When Python reads a name, it looks through the relevant scopes, including local, enclosing function, module, and built-in namespaces. An assignment inside an ordinary function makes that name local unless declared otherwise. Avoid relying on global and nonlocal to repair unclear data flow at this stage. Passing required information as parameters and returning results usually makes a beginner function easier to understand and test.

local_rebinding.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

03Mutation can still be visible outside

Passing a list binds the parameter to the same list object supplied by the caller. Rebinding that parameter would be local, but appending through it mutates the shared list. Local scope does not create an automatic protective copy of argument objects. This is the same reference behavior you studied in mutability and copying, now crossing a function boundary.

A mutating function can be appropriate, but its name and documentation should make that behavior clear. If the caller needs the original collection preserved, construct a new result or copy the necessary structure. Decide whether your function is meant to change supplied data before implementing it. Surprising mutation is especially confusing when a caller assumes that merely computing a report could not alter its source records.

shared_argument.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

04Defaults are created when def executes

A default expression is evaluated when the function definition executes, not freshly for every call. A list used directly as a default can therefore be shared by later calls. Appending to that default list can make a second call unexpectedly retain data from the first. This is a lifecycle issue: the same object remains attached to the function as its default.

Use None as the default when an omitted argument should produce a fresh mutable container. Check for None inside the function and create a new list there. This distinguishes omission from an explicitly supplied empty list, which is a real object the caller may expect you to use. The pattern below makes independent results when no list is passed and intentionally mutates a supplied list when one is passed.

fresh_default.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
LET IT CLICK

The ideas worth keeping.

  • Positional arguments bind by order; keyword arguments bind by name.
  • Local rebinding is isolated, but mutating a shared argument can affect the caller.
  • Default objects are created at definition time; use None for fresh per-call containers.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Clear defaults and keywords

Define greeting(name, prefix='Hello') that returns prefix followed by a comma, a space, and the name. Demonstrate the default with Ada and a keyword prefix='Welcome' with Mira.

your_turn_1.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.pyPython
def greeting(name, prefix="Hello"):    return f"{prefix}, {name}"print(greeting("Ada"))print(greeting("Mira", prefix="Welcome"))

The default supplies Hello only when prefix is omitted. Naming prefix in the second call makes the customization easy to understand.

02

Return an updated plan without mutation

Define with_review(tasks) that returns a new flat list containing the original items followed by Review. Demonstrate it with ['Read'] and print both the original and result.

your_turn_2.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.pyPython
def with_review(tasks):    updated = tasks.copy()    updated.append("Review")    return updatedoriginal = ["Read"]result = with_review(original)print(original)print(result)

The shallow copy is enough because this operation changes only the outer list. The original remains ['Read'], while the returned list is ['Read', 'Review'].

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01Why can def add(x, items=[]): retain entries between calls?
02A function executes values.append(4) on a list argument. Can the caller observe the change?
03Which call correctly overrides quantity in def total(price, quantity=1)?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Clear defaults and keywords

Define greeting(name, prefix='Hello') that returns prefix followed by a comma, a space, and the name. Demonstrate the default with Ada and a keyword prefix='Welcome' with Mira.

EXPECTED OUTPUT
greeting("Ada")
greeting("Mira" prefix="Welcome")
challenge.pyPython 3
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this chapter, when you want a second angle or the full details.

One chapter closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock chapter completion.