مرکزی مواد پر جائیں

Default Values and Keyword Arguments

In Lesson 1, James wrote functions where every parameter was required. Every call needed every argument:

def reading_time(word_count: int, wpm: int) -> float:
return word_count / wpm

print(reading_time(1500, 250))
print(reading_time(2000, 250))
print(reading_time(800, 250))

Output:

6.0
8.0
3.2

James stares at his three calls. "I typed 250 three times. Most people read at 250 words per minute. Can I make that the automatic choice so I do not have to type it every time?"

"Yes," Emma says. "That is called a default value. You write = 250 after the type, and Python uses 250 automatically whenever the caller does not provide a different number."

A default value is like a pre-filled form field. The form already has an answer, but you can change it if you want. If you leave it alone, the pre-filled answer is used.


How to Write a Default Value

Add = value after the type annotation. The pattern is param: type = default:

def reading_time(word_count: int, wpm: int = 250) -> float:
return word_count / wpm

The = 250 means: "if the caller does not give a value for wpm, use 250."

Now you can call this function in different ways:

# Use the default (wpm=250)
time_a: float = reading_time(1500)
print(time_a)

# Override the default with a positional argument
time_b: float = reading_time(1500, 300)
print(time_b)

# Override with a keyword argument (most readable)
time_c: float = reading_time(1500, wpm=200)
print(time_c)

Output:

6.0
5.0
7.5

The first call uses the default wpm=250. The second overrides it with 300. The third uses a keyword argument wpm=200, which makes the call easier to read because you can see which parameter you are setting.

Rule: Parameters with defaults must come after parameters without defaults. def f(x: int = 0, y: int) is a SyntaxError because Python would not know where to put the positional argument.


Positional Arguments: Order Matters

When you call a function by just passing values without names, those are called positional arguments. Python matches them to parameters by position: the first value goes to the first parameter, the second to the second, and so on.

def note_summary(title: str, word_count: int, is_draft: bool = False) -> str:
return f"{title} ({word_count} words, draft={is_draft})"

# Positional: order must match the signature
print(note_summary("My Note", 350, True))

Output:

My Note (350 words, draft=True)

"My Note" goes into title (first parameter), 350 goes into word_count (second), True goes into is_draft (third). If you swap the order, you get wrong results or an error:

# Wrong order: 350 goes into title, "My Note" goes into word_count
print(note_summary(350, "My Note", True))

Pyright error:

error: Argument of type "int" is not assignable to parameter "title" of type "str"

With positional arguments, order is everything. Get it wrong, and the values end up in the wrong parameters.


Keyword Arguments: Naming What You Pass

Positional arguments work, but they have a problem. Look at this call:

note_summary("My Note", 350, True)

What does 350 mean? What does True mean? You cannot tell without looking at the function signature. Now look at the same call with keyword arguments:

note_summary(title="My Note", word_count=350, is_draft=True)

Now every value has a label. You can read the call and understand it without looking anywhere else. A keyword argument uses the parameter name followed by = and the value.

Here is the full example:

def note_summary(title: str, word_count: int, is_draft: bool = False) -> str:
return f"{title} ({word_count} words, draft={is_draft})"

# Positional: you have to remember the order
print(note_summary("My Note", 350, True))

# Keyword: the code explains itself
print(note_summary(title="My Note", word_count=350, is_draft=True))

Output:

My Note (350 words, draft=True)
My Note (350 words, draft=True)

Both calls produce the same result. The keyword version takes a few more characters but is much easier to read. You can also mix: positional for the first obvious arguments, keyword for the rest:

print(note_summary("My Note", 350, is_draft=True))

Output:

My Note (350 words, draft=True)

Keyword arguments can be in any order

Because Python matches by name (not position), you can write keyword arguments in any order:

print(note_summary(is_draft=True, word_count=350, title="My Note"))

Output:

My Note (350 words, draft=True)

Python sees title=, word_count=, and is_draft= and puts each value in the right place regardless of order.


When to Use Defaults vs When to Require

Not every parameter should have a default. The question is: does this parameter have a "normal" value that most callers will use?

ParameterDefault?Why
word_count: intNo defaultEvery note has a different word count
wpm: int = 250Default 250Most people read at ~250 wpm
title: strNo defaultEvery note has a unique title
is_draft: bool = FalseDefault FalseMost notes are not drafts
max_results: int = 10Default 10Most searches want ~10 results
query: strNo defaultEvery search has a different query

Rule of thumb: if you can answer "what would most callers pass?", make that the default. If every call needs a different value, make it required.

Rule: Parameters with defaults must come after parameters without defaults. def f(x: int = 0, y: int) is a SyntaxError because Python would not know where to put the positional arguments.


PRIMM-AI+ Practice: Defaults and Keywords

Predict [AI-FREE]

Press Shift+Tab to enter Plan Mode before predicting.

Look at these function calls. Predict the output for each. Write your predictions and a confidence score from 1 to 5 before checking.

def greet(name: str, greeting: str = "Hello") -> str:
return f"{greeting}, {name}!"

print(greet("James"))
print(greet("Emma", "Hi"))
print(greet("James", greeting="Hey"))
print(greet(greeting="Yo", name="Bob"))
Check your predictions

Call 1: greet("James") uses the default greeting="Hello". Result: Hello, James!

Call 2: greet("Emma", "Hi") overrides the default positionally. Result: Hi, Emma!

Call 3: greet("James", greeting="Hey") overrides with a keyword argument. Result: Hey, James!

Call 4: greet(greeting="Yo", name="Bob") uses all keyword arguments in reversed order. Python matches by name, not position. Result: Yo, Bob!

If you predicted all four correctly, you understand both defaults and keyword arguments. The tricky one is Call 4: keyword arguments can appear in any order because Python matches them by name.

Run

Press Shift+Tab to exit Plan Mode.

Create a file with the greet function and all four calls. Run it and compare to your predictions.

Investigate

Write one sentence explaining why greet(greeting="Yo", name="Bob") works even though the arguments are in the opposite order from the signature.

If you want to go deeper, run /investigate @greet.py in Claude Code and ask how Python resolves keyword arguments internally.

Modify

Add a third parameter punctuation: str = "!" to greet. Update the return to use it: f"{greeting}, {name}{punctuation}". Call the function with punctuation="." and verify the output changes.

Make [Mastery Gate]

Without looking at any examples, write 2 function signatures with meaningful default values:

  1. A function that formats a price with a currency symbol (default: "$")
  2. A function that creates a tag string from a tag name and a prefix (default: "topic")

Write at least one call for each that uses the default, and one that overrides it. Run pyright to confirm zero errors.


Try With AI

Opening Claude Code

If Claude Code is not already running, open your terminal, navigate to your SmartNotes project folder, and type claude. If you need a refresher, Chapter 44 covers the setup.

Prompt 1: Discover When Defaults Help

I have this function signature:

def search_notes(query: str, case_sensitive: bool, max_results: int) -> list[str]:
...

Every call requires all three arguments. Which parameters should
have defaults, and what should the defaults be? Explain your
reasoning for each choice.

Read AI's recommendations. It will likely suggest case_sensitive: bool = False and max_results: int = 10. Evaluate: do those defaults match the "common case"? Would you choose different values? Tell AI if you disagree with any default.

What you're learning: You are evaluating whether AI's default choices match real usage patterns. The signature is yours; AI suggests, you decide.

Prompt 2: Keyword Arguments for Readability

Rewrite these three function calls using keyword arguments so
that someone reading the code can understand what each argument
means without looking at the function signature:

note_summary("My Note", 350, True)
reading_time(1500, 200)
truncate_title("Hello World", 5)

Compare AI's rewritten calls to the originals. Which version would you prefer to read in a codebase you maintain? The keyword versions take more characters but carry their meaning with them.

What you're learning: You are practicing the habit of writing self-documenting code. Keyword arguments are a small investment in readability that pays off every time someone reads the code.


James reviews his SmartNotes functions. "Defaults for common values, keyword arguments for readability. And parameters with defaults must come last."

"You forgot one thing," Emma says. "The signature tells pyright and AI what types to expect. But it does not tell them what the function does. A function called process_data with two str parameters could do anything."

"So I need to describe the purpose somewhere?"

"That is what a docstring is. Lesson 3. You write a short description inside the function that says what it does, not how. The signature plus the docstring together become a complete specification."